diff -ur --new-file old/atm/.kernel new/atm/.kernel --- old/atm/.kernel Tue Nov 18 23:15:50 1997 +++ new/atm/.kernel Fri Jan 16 15:47:19 1998 @@ -1,2 +1,2 @@ # this file is used to control automated generation of differences -2.1.65 +2.1.79 diff -ur --new-file old/atm/CHANGES new/atm/CHANGES --- old/atm/CHANGES Wed Nov 19 03:58:51 1997 +++ new/atm/CHANGES Fri Mar 13 22:04:04 1998 @@ -1,3 +1,97 @@ +Version 0.33 to 0.34 (13-MAR-1998) +==================== + +Bug fixes +--------- + + - eni.c didn't include config.h (fix by Pete Wyckoff) + - (yet another) VCC list handling bug (fixed by Heikki Vatiainen) + - kernel also applied idle timeout to CLIP PVCs + - make clean didn't remove test/errnos.inc + - atmsigd errored as_connect and as_accept with as_close instead of as_error + - eni: bandwidth was sometimes reserved for UBR VCs + - eni: checking of bandwidth changes was broken + - eni: error handling after failed bw change checks destroyed the free list + - test/errnos.inc sometimes wasn't generated because of mtime granularity (fix + by Brian Armstrong and Corinne Rosier) + - fixed use of return code of get/put_user and copy_from/to_user + - kernel: fixed a few minor race conditions + - ATM_GETADDR left address list locked on fault + - maximum length of high layer information was 7 bytes instead of 8 for ISO + and User Specific high layer information (reported by Damian Gilmurray) + - some tools didn't include errno.h although they use errno or Exxx + - atmsigd usually accessed deallocated memory when writing traces, which + sometimes led to crashes (reported by Heikki Vatiainen) + - indentation of the first two lines of UNI signaling messages in traces was + missing + - LANE: duplicate data direct connections to entities where we already + have a connection are now forbidden. LES and BUS can now co-reside. + (Reported by Jean-Francois Moine, fixed by Heikki Vatiainen) + - LANE: plugged a file descriptor leak (by Heikki Vatiainen) + - atmsigd.conf.4 incorrectly stated that diagnostics must have a higher + priority than the specified level to get printed (they're also printed if + their priority is equal to that level) + - zatm driver didn't virt_to_bus the back pointer of TX rings, leading to + crash after sending the 32nd PDU of a VCC (reported by Ajay Bakre) + - zatm_feedback sometimes returned with interrupts disabled + - ENI driver didn't treat requests for UBR at link speed as "unlimited" and + allocated one shaper for each such VCC + - atm_async_release_vcc now has its own flag ATM_VF_CLOSE. Overloading + ATM_VF_RELEASED caused hung SVCs under some conditions. + - atmsigd sometimes released listening sockets before kernel completed its + cleanup, yielding warnings and zombies + - atmsigd accessed already deallocated data structures when handling + unparseable signaling messages + + +New features +------------ + + - upgraded to the 2.1.79 kernel + - CLIP now handles NETDEV_CHANGE (proposed by Pete Wyckoff; untested) + - various minor signaling changes for operation as switch control + - new device operation proc_read: device drivers can now register in /proc + (e.g. /proc/atm/eni:0) + - added some more BHLI definitions to include/atmsap.h, including draft + mapping of well-known TCP/UDP port numbers + - added support for TIOCOUTQ/TIOCINQ on native ATM + - new library function sap_equal + - added convenience function atmpvc_addr_in_use to linux/atm.h + - major overhaul of "isp", which is now a good tool for signaling regression + tests. See atm/test/README.isp + - LANE can now be compiled as a kernel module (by Heikki Vatiainen) + - new tool debug/svctor.c to torture signaling by setting up and releasing + lots of SVCs (see the source for details) + +Other changes +------------- + + - cleaned up the copying terms: libraries are now covered by LGPL instead of + GPL and qgen doesn't "taint" the code it generates + - atmarpd: IP addresses are now __u32 instead of unsigned long + - atmarpd: changed printf("... %08x ...",(unsigned long) ptr) to %p ...",ptr + - /proc support now allocates inode numbers dynamically + - added comment to clarify motivation for useless buffer alignment in aread.c + (reported by Jeon Jong Hwan) + - suni.c and uPD98402.c: SONET_GETSTATZ no longer clears the statistics if the + copy faults + - ilmid should now work on any interface (patch by Heikki Vatiainen) + - changed all __uNN of tools to uintNN_t for glibc2-compatibility + - added stdint.h to lib for compatibility with future versions of glibc2 + - various other evil hacks in tools to make things compile with glibc2 + - the NIC debugging programs ed, encopy, endump, zndump, and znth are no + longer built and installed by default + - for compatibility with POSIX 1003.1g, accept now returns ECONNABORTED + instead of ECONNREFUSED if connection is already gone (proposed by Heikki + Vatiainen) + - listening sockets now return instantly if the signaling demon dies + - various minor LANE updates to track API changes (by Heikki Vatiainen) + - SUNI now also warns if signal is missing at initialization time + - zatm: added work-around for unfair buffer space accounting + - clarified some of atmarpd's diagnostics + - documentation updates + + Version 0.32 to 0.33 (19-NOV-1997) ==================== diff -ur --new-file old/atm/COPYING new/atm/COPYING --- old/atm/COPYING Mon Sep 1 12:29:52 1997 +++ new/atm/COPYING Tue Feb 17 17:13:16 1998 @@ -1,6 +1,6 @@ Program code, documentation and auxiliary programs, except for the parts listen below, are -Copyright 1995-1997 EPFL-LRC +Copyright 1995-1998 EPFL-LRC/ICA All rights reserved. This package is free software; you can redistribute it and/or modify @@ -9,6 +9,15 @@ (at your option) any later version. See the file COPYING.GPL for details. + + +The libraries libatm, libatmd, libarequipa (in atm/lib/), libsaal (in +atm/saal/), and qlib (in atm/qgen/) are covered by the more permissive +Library General Public License. See the file COPYING.LGPL for details. + +Code generated by qgen is only constrained by whatever usage +restrictions apply to the message structure definition used as input, +i.e. the use of qgen for translation does not create any restrictions. ilmid is Copyright (C) 1995 Telecommunications & Information Sciences Laboratory, The University of Kansas diff -ur --new-file old/atm/COPYING.LGPL new/atm/COPYING.LGPL --- old/atm/COPYING.LGPL Thu Jan 1 01:00:00 1970 +++ new/atm/COPYING.LGPL Tue Feb 17 16:56:25 1998 @@ -0,0 +1,481 @@ + GNU LIBRARY GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 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. + +[This is the first released version of the library GPL. It is + numbered 2 because it goes with version 2 of the ordinary GPL.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Library General Public License, applies to some +specially designated Free Software Foundation software, and to any +other libraries whose authors decide to use it. You can use it for +your libraries, 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 library, or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link a program with the library, you must provide +complete object files to the recipients so that they can relink them +with the library, after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + Our method of protecting your rights has two steps: (1) copyright +the library, and (2) offer you this license which gives you legal +permission to copy, distribute and/or modify the library. + + Also, for each distributor's protection, we want to make certain +that everyone understands that there is no warranty for this free +library. If the library is modified by someone else and passed on, we +want its recipients to know that what they have is not the original +version, 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 companies distributing free +software will individually obtain patent licenses, thus in effect +transforming the program into proprietary software. To prevent this, +we have made it clear that any patent must be licensed for everyone's +free use or not licensed at all. + + Most GNU software, including some libraries, is covered by the ordinary +GNU General Public License, which was designed for utility programs. This +license, the GNU Library General Public License, applies to certain +designated libraries. This license is quite different from the ordinary +one; be sure to read it in full, and don't assume that anything in it is +the same as in the ordinary license. + + The reason we have a separate public license for some libraries is that +they blur the distinction we usually make between modifying or adding to a +program and simply using it. Linking a program with a library, without +changing the library, is in some sense simply using the library, and is +analogous to running a utility program or application program. However, in +a textual and legal sense, the linked executable is a combined work, a +derivative of the original library, and the ordinary General Public License +treats it as such. + + Because of this blurred distinction, using the ordinary General +Public License for libraries did not effectively promote software +sharing, because most developers did not use the libraries. We +concluded that weaker conditions might promote sharing better. + + However, unrestricted linking of non-free programs would deprive the +users of those programs of all benefit from the free status of the +libraries themselves. This Library General Public License is intended to +permit developers of non-free programs to use free libraries, while +preserving your freedom as a user of such programs to change the free +libraries that are incorporated in them. (We have not seen how to achieve +this as regards changes in header files, but we have achieved it as regards +changes in the actual functions of the Library.) The hope is that this +will lead to faster development of free libraries. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, while the latter only +works together with the library. + + Note that it is possible for a library to be covered by the ordinary +General Public License rather than by this special one. + + GNU LIBRARY GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library which +contains a notice placed by the copyright holder or other authorized +party saying it may be distributed under the terms of this Library +General Public License (also called "this License"). Each licensee is +addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, 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 library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete 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 distribute a copy of this License along with the +Library. + + 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 Library or any portion +of it, thus forming a work based on the Library, 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) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +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 Library, 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 Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you 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. + + If distribution of 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 satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also compile or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + c) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + d) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. 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. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library 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. + + 9. 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 Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +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. + + 11. 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 Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library 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 Library. + +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. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library 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. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Library 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 Library +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 Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +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 + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "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 +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. 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 LIBRARY 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 +LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), 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 Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. 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. + + + Copyright (C) + + This 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. + + This 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 this library; if not, write to the Free + 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. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! diff -ur --new-file old/atm/Makefile new/atm/Makefile --- old/atm/Makefile Mon Sep 22 18:25:29 1997 +++ new/atm/Makefile Mon Feb 16 16:34:17 1998 @@ -2,8 +2,7 @@ # "lib" must appear before anything else # "maint" must appear after "qgen" -DIRS=lib ip test debug qgen saal sigd maint arpd ilmid aqd man #extra -# led lane -- temporarily removed +DIRS=lib ip test debug qgen saal sigd maint arpd ilmid aqd man led lane #extra all: for n in $(DIRS); do $(MAKE) -C $$n || exit; done diff -ur --new-file old/atm/README new/atm/README --- old/atm/README Tue Nov 18 23:40:10 1997 +++ new/atm/README Thu Mar 12 18:29:54 1998 @@ -1,13 +1,15 @@ -ATM on Linux, release 0.33 (alpha) by Werner Almesberger, EPFL LRC -====================================== werner.almesberger@lrc.di.epfl.ch +ATM on Linux, release 0.34 (alpha) by Werner Almesberger, EPFL ICA +============================================== Werner.Almesberger@epfl.ch This is experimental software. There are known major bugs and certainly even many more yet unknown problems. Internal and external interfaces are far from being stable. In fact, they change daily. Use at your own risk. This package contains a kernel patch for ATM protocol stacks and for ATM -device drivers, source for management and test tools, and this -description. +device drivers, source for demons, management and test tools, and some +documentation. + +The kernel patch is relative to the "standard" 2.1.79 kernel. The following network devices are supported: ATM over TCP pseudo device for "dry runs" @@ -28,11 +30,11 @@ "raw" unreliable ATM transport over AAL5 IP over ATM (NULL or SNAP encapsulation) ATMARP as defined in RFC1577 (client and server) - LAN Emulation (client and server side) (*) + LAN Emulation (client and server side) Arequipa (Application REQUested IP over ATM) (*) ANS (ATM Name Service) -(* Not included in this version, but expected to follow early '98) +(* Not included in this version, but expected to follow soon) The API is based on the Linux ATM API proposed on the linux-atm mailing list. diff -ur --new-file old/atm/Rules.make new/atm/Rules.make --- old/atm/Rules.make Sat Nov 8 00:17:03 1997 +++ new/atm/Rules.make Wed Mar 4 10:09:33 1998 @@ -32,7 +32,7 @@ CFLAGS_NOOPT=$(CFLAGS_NOWARN) -Wall -Wshadow -Wpointer-arith -Wcast-align \ -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes \ #-Wmissing-declarations (gcc 2.6.x only) #-Wconversion (breaks inline) -CFLAGS_OPT=-O2 +CFLAGS_OPT=#-O2 CFLAGS=$(CFLAGS_NOOPT) $(CFLAGS_OPT) $(CFLAGS_PRIVATE) CFLAGS_LEX=$(CFLAGS_NOWARN) $(CFLAGS_OPT) CFLAGS_YACC=$(CFLAGS_NOWARN) $(CFLAGS_OPT) -DYY_USE_CONST @@ -59,6 +59,7 @@ process 0755 $(INSTUSRBIN) $(USRPGMS); \ process 0644 $(INSTLIB) $(GENLIBS); \ process 0644 $(INSTHDR) $(SYSHDR); \ + optprocess 0644 $(INSTHDR) $(OPTSYSHDR); \ process 0644 $(INSTMAN1) $(MAN1); \ process 0644 $(INSTMAN4) $(MAN4); \ process 0644 $(INSTMAN7) $(MAN7); \ @@ -96,12 +97,17 @@ @process() { if [ ! -z "$$3" ]; then mode=$$1; dir=$$2; \ shift 2; echo "install -c -m $$mode $$* $$dir"; \ install -c -m $$mode $$* $$dir; fi; }; \ + optprocess() { [ -z "$$3" -o -r "$$3" ] || process $$*; }; \ $(PROCLIST) +# optprocess is only defined for a single file. Right now we're using it only +# for stdint.h + instdirs: @process() { if [ ! -z "$$3" ]; then \ echo "install -d $$2"; \ install -d $$2; fi; }; \ + optprocess() { :; }; \ $(PROCLIST) uninstall: diff -ur --new-file old/atm/USAGE new/atm/USAGE --- old/atm/USAGE Wed Nov 19 03:57:48 1997 +++ new/atm/USAGE Fri Mar 13 22:07:11 1998 @@ -1,4 +1,4 @@ -Usage instructions - ATM on Linux, release 0.33 (alpha) +Usage instructions - ATM on Linux, release 0.34 (alpha) --------------------------------------------------------- For updates of ATM on Linux, please check the Web page at @@ -17,9 +17,9 @@ In order to install this package, you need - the package itself - ftp://lrcftp.epfl.ch/pub/linux/atm/dist/atm-0.33.tar.gz - - the Linux kernel, version 2.1.65, e.g. from - ftp://ftp.kernel.org/pub/linux/kernel/v2.1/linux-2.1.65.tar.gz + ftp://lrcftp.epfl.ch/pub/linux/atm/dist/atm-0.34.tar.gz + - the Linux kernel, version 2.1.79, e.g. from + ftp://ftp.kernel.org/pub/linux/kernel/v2.1/linux-2.1.79.tar.gz - Perl, version 4 or 5 - if you want memory debugging: MPR version 1.6, e.g. from ftp://sunsite.unc.edu/pub/Linux/devel/lang/c/mpr-1.6.tar.gz @@ -33,11 +33,11 @@ all the files listed above there. Then extract the ATM on Linux distribution: -tar xfz atm-0.33.tar.gz +tar xfz atm-0.34.tar.gz and the kernel source: -tar xfz linux-2.1.65.tar.gz +tar xfz linux-2.1.79.tar.gz Finally, you can extract the ATM-related patches: @@ -61,8 +61,8 @@ atm/led/ LAN Emulation demon: led atm/lane/ LAN Emulation servers: bus, lecs, les atm/aqd/ Arequipa demon: aqpvc, arequipad - atm/debug/ Debugging tools: aqtest, delay, ed, encopy, endump, zndump, - and znth + atm/debug/ Debugging tools: aqtest, delay, ed, encopy, endump, svctor, + zndump, and znth atm/lib/ Libraries for applications and demons atm/doc/ Documentation in LaTeX and conversion tools atm/man/ Miscellaneous man pages @@ -74,43 +74,22 @@ -------------------- Now, change links (if necessary) and do the usual make config , make -menuconfig , or make xconfig . You should find the following new options: +menuconfig , or make xconfig . First, enable -Asynchronous Transfer Mode (ATM) (CONFIG_ATM) - Enable single-copy (CONFIG_MMU_HACKS) - Extended debugging for single-copy (CONFIG_MMU_HACKS_DEBUG) +Prompt for development and/or incomplete code/drivers + (CONFIG_EXPERIMENTAL) + +You should find the following new options: + +Asynchronous Transfer Mode (ATM, EXPERIMENTAL) (CONFIG_ATM) Classical IP over ATM (CONFIG_ATM_CLIP) - Application REQUested IP over ATM (CONFIG_AREQUIPA) - LANE support (CONFIG_ATM_LANE) + LAN Emulation (LANE) support (CONFIG_ATM_LANE) ATM over TCP (CONFIG_ATM_TCP) Efficient Networks ENI155P (CONFIG_ATM_ENI) Enable extended debugging (CONFIG_ATM_ENI_DEBUG) ZeitNet ZN1221/ZN1225 (CONFIG_ATM_ZATM) Enable extended debugging (CONFIG_ATM_ZATM_DEBUG) Enable usec resolution timestamps (CONFIG_ATM_ZATM_EXACT_TS) -Rolfs TI TNETA1570 (CONFIG_ATM_TNETA1570) - Enable extended debugging (CONFIG_ATM_TNETA1570_DEBUG) -IDT 77201 (NICStAR) (CONFIG_ATM_NICSTAR) - -The "MMU hacks" add single-copy support for raw AAL5 on adapters whose -driver supports this (currently only the ENI155p). Extended debugging -should only be enabled when tracing specific problems, because it slows -down the drivers, and it may introduce new race conditions. - -The TNETA1570 driver is for a board developed by Rolf Fiedler at TU -Chemnitz, see also ftp://ftp.infotech.tu-chemnitz.de/pub/linux-atm . - -Note that the file drivers/atm/nicstar.h contains a few configurable -settings for the IDT 77201 driver. - -Support for a simple type of serial consoles is automatically added by the -ATM patch. If you're using LILO, you can enable it by putting a line like - - append="scon=" - -with indicating the serial port (equal to the first number in the -serial= line) into /etc/lilo.conf. Use the SERIAL option of LILO to make -LILO use the serial console too. Then build your kernel and reboot. @@ -299,14 +278,17 @@ ------------------ Some status information about the ATM subsystem can be obtained through -files in /proc/atm. /proc/atm/arp contains information specific to ATMARP, -see section "ATMARP demon". +files in /proc/atm. /proc/atm/arp contains information specific to +Classical IP over ATM, see section "CLIP". /proc/atm/devices lists all active ATM devices. For each device, the interface number, the type label, the end system identifier (ESI), and statistics are shown. The statistics correspond to the ones available via atmdiag. +Individual ATM devices may register entries of the form : +(e.g. eni:0 ) which contain device-specific information. + /proc/atm/pvc and /proc/atm/svc list all PVC and SVC sockets. For both types of sockets, the interface, VPI and VCI numbers are shown. For PVCs, this is followed by the AAL and the traffic class and the selected PCR for @@ -545,7 +527,7 @@ If no interface number is specified, ilmid serves interface 0. atmsigd should already be running when ilmid is started, Use the -b option to -make sure they're properly synchronized (see section "ATMARP demon"). +make sure they're properly synchronized (see section "CLIP"). The agent supports only the address registration procedures specified in section 5.8 of the ATM Forum's UNI 3.1 specification. These procedures @@ -685,67 +667,15 @@ IP over ATM =========== -IP over ATM is supported using two modules:* the CLIP module only supports -PVCs and only handles encapsulation according to RFC1483 [2]. InARP -(defined in RFC1577 [3]) is not supported by this mechanism. - - * The term "module" is used here for a functional software component, - not for a loadable kernel module. - -The more advanced ATMARP module includes full support for PVCs and SVCs -(including ATMARP and InARP) as specified in RFC1577, but is still a bit -less reliable than CLIP. - -CLIP will be phased out in the near future. +IP over ATM is supported with Classical IP over ATM (CLIP, defined in +RFC1577 [2]), and LAN Emulation. CLIP ---- -Limited IP over ATM for PVCs is supported in this release using the clip -program. Please be aware that it might not interoperate with other -implementations, because InARP is not supported. - -VCCs are used as IP point to point links, so contrary to what RFC1577 -suggests, VCC selection is a routing decision and not a matter of address -resolution. - -For a better but still immature mechanism see section "ATMARP demon". - -First, the VCCs have to be established. Become root on both machines and -run clip (see clip.8) on each of them, e.g.: - -a# clip 0.40 -b# clip 0.40 - -For CBR connections, specify the desired peak cell rate as the second -argument. The default encapsulation is LLC/SNAP, but NULL encapsulation can -be selected with the option -0 (that's "zero", not "oh"). - -Next, the interfaces have to be configured: - - # /sbin/ifconfig atm0 up dstaddr - -e.g. - -a# /sbin/ifconfig atm0 up 10.0.0.1 dstaddr 10.0.0.2 -b# /sbin/ifconfig atm0 up 10.0.0.2 dstaddr 10.0.0.1 - -Finally, you have to add the routes: - -a# /sbin/route add 10.0.0.2 -b# /sbin/route add 10.0.0.1 - -Test the connection with ping: - -a% ping 10.0.0.2 - - -ATMARP demon ------------- - -For ATMARP, a demon process is used to generate and answer ARP queries. The -actual kernel part maintains a small lookup table only containing partial +A demon process is used to generate and answer ARP queries. The actual +kernel part maintains a small lookup table only containing partial information. Man pages: atmarpd.8, atmarp.8 @@ -774,13 +704,12 @@ # atmarp -c # ifconfig atm0 up - # route add -net + e.g. # atmarp -c atm0 # ifconfig atm0 10.0.0.3 up -# route add -net 10.0.0.0 If only PVCs will be used, they can now be created with a command like @@ -792,7 +721,7 @@ When using SVCs, some additional configuration work may be necessary. If the machine is acting as the ATMARP server on that LIS, no additional -configuration is necessary. Otherwise, the ATM address of the ATMARP server +configuration is required. Otherwise, the ATM address of the ATMARP server has to be configured. This is done by creating an entry for the network address with the option arpsrv set, e.g. @@ -820,34 +749,13 @@ Man pages: bus.8, lecs.8, les.8, and zeppelin.8 - -Arequipa --------- - -Arequipa (Application REQUested IP over ATM, [4]) is an extension to IP -over ATM that adds support for using direct ATM connections (with QOS -parameters, etc.) to carry traffic between INET sockets. On a system that -should use Arequipa connections, the Arequipa demon has to run. - -Man page: arequipad.8 - -The status of Arequipa connections is shown in /proc/atm/arequipa. - -If atmsigd is not running, all attempts to use Arequipa fail and the ioctls -set errno to EUNATCH. - -The following example illustrates the use of Arequipa with ttcp_atm. A -machine "a" sends data to a machine "b", which is also registered with that -name in the DNS. Furthermore, "b" has an entry with the name "b-atm" in the -/etc/hosts.atm file of "a". First, execute on "b": - -# arequipad -b -# ttcp_atm -r -s -Q dummy - -then run on "a": - -# arequipad -b -# ttcp_atm -t -s -Q b-atm b +%# arequipad -b +%# ttcp_atm -r -s -Q dummy +% + +%# arequipad -b +%# ttcp_atm -t -s -Q b-atm b +% References @@ -855,10 +763,5 @@ [1] Almesberger, Werner. Linux ATM API, ftp://lrcftp.epfl.ch/pub/linux/atm/api/ , July 1996. - [2] Heinanen, Juha. Multiprotocol Encapsulation over ATM Adaptation - Layer 5, RFC1483, July 1993. - [3] Laubach, Mark. Classical IP and ARP over ATM, RFC1577, January + [2] Laubach, Mark. Classical IP and ARP over ATM, RFC1577, January 1994. - [4] Almesberger, Werner; Le Boudec, Jean-Yves; Oechslin, Philippe. - Application REQuested IP over ATM (AREQUIPA) (work in progress), - Internet Draft draft-almesberger-arequipa-01.txt , June 1996. diff -ur --new-file old/atm/VERSION new/atm/VERSION --- old/atm/VERSION Wed Nov 19 01:14:37 1997 +++ new/atm/VERSION Fri Mar 6 21:34:28 1998 @@ -1 +1 @@ -0.33 +0.34 diff -ur --new-file old/atm/arpd/Makefile new/atm/arpd/Makefile --- old/atm/arpd/Makefile Mon Oct 20 23:28:17 1997 +++ new/atm/arpd/Makefile Fri Mar 13 22:02:38 1998 @@ -10,4 +10,3 @@ atmarpd: $(OBJS) $(CC) $(LDFLAGS) -o atmarpd $(OBJS) $(LIBS) $(LDLIBS) - diff -ur --new-file old/atm/arpd/arp.c new/atm/arpd/arp.c --- old/atm/arpd/arp.c Wed Nov 19 01:44:54 1997 +++ new/atm/arpd/arp.c Fri Mar 6 21:33:56 1998 @@ -1,9 +1,10 @@ /* arp.c - ARP state machine */ -/* Written 1995-1997 by Werner Almesberger, EPFL-LRC */ +/* Written 1995-1998 by Werner Almesberger, EPFL-LRC/ICA */ #include +#include #include #include #include @@ -11,7 +12,7 @@ #include #include /* for linux/if_arp.h */ #include /* for ntohs, etc. */ -#include /* for MAX_ADDR_LEN for if_arp.h */ +#define _LINUX_NETDEVICE_H /* very crude hack for glibc2 */ #include #include #include @@ -70,15 +71,21 @@ } -void discard_entry(ENTRY *entry) +void discard_vccs(ENTRY *entry) { VCC *vcc,*next; - STOP_TIMER(entry); for (vcc = entry->vccs; vcc; vcc = next) { next = vcc->next; discard_vcc(vcc); } +} + + +void discard_entry(ENTRY *entry) +{ + STOP_TIMER(entry); + discard_vccs(entry); if (!entry->itf) Q_REMOVE(unknown_incoming,entry); else { if (entry == entry->itf->arp_srv) entry->itf->arp_srv = NULL; @@ -118,7 +125,7 @@ } -static void vcc_detach(ENTRY *entry) +void vcc_detach(ENTRY *entry) { ENTRY *walk; @@ -138,7 +145,7 @@ } -static void put_ip(unsigned char **here,unsigned long ip,unsigned char *len) +static void put_ip(unsigned char **here,uint32_t ip,unsigned char *len) { if (!ip) { *len = 0; @@ -182,8 +189,8 @@ 0x06 }; -static void send_arp(int fd,unsigned short op,unsigned long local_ip, - struct sockaddr_atmsvc *local_addr,unsigned long remote_ip, +static void send_arp(int fd,unsigned short op,uint32_t local_ip, + struct sockaddr_atmsvc *local_addr,uint32_t remote_ip, struct sockaddr_atmsvc *remote_addr) { struct sockaddr_atmsvc local; @@ -211,7 +218,7 @@ } -static void arp_request(ITF *itf,unsigned long ip) +static void arp_request(ITF *itf,uint32_t ip) { VCC *vcc; @@ -233,7 +240,7 @@ static void inarp_for_itf(VCC *vcc,ITF *itf) { if (itf->local_ip) { - diag(COMPONENT,DIAG_DEBUG," on itf %d",itf->number); + diag(COMPONENT,DIAG_DEBUG," for itf %d",itf->number); assert(vcc->entry); send_arp(vcc->fd,ARPOP_InREQUEST,itf->local_ip,NULL,0, vcc->entry->svc ? vcc->entry->addr : NULL); @@ -246,7 +253,7 @@ VCC *vcc; ITF *itf; - diag(COMPONENT,DIAG_DEBUG,"sending InARP request"); + diag(COMPONENT,DIAG_DEBUG,"sending an InARP request for each IP interface"); for (vcc = entry->vccs; vcc; vcc = vcc->next) if (!vcc->connecting) if (entry->itf) inarp_for_itf(vcc,entry->itf); @@ -254,7 +261,7 @@ } -static void arp_nak(VCC *vcc,unsigned long src_ip,unsigned long tgt_ip, +static void arp_nak(VCC *vcc,uint32_t src_ip,uint32_t tgt_ip, struct sockaddr_atmsvc *tgt_addr) { diag(COMPONENT,DIAG_DEBUG,"sending ARP NAK"); @@ -262,8 +269,8 @@ } -static void arp_reply(VCC *vcc,unsigned long src_ip, - struct sockaddr_atmsvc *src_addr,unsigned long tgt_ip, +static void arp_reply(VCC *vcc,uint32_t src_ip, + struct sockaddr_atmsvc *src_addr,uint32_t tgt_ip, struct sockaddr_atmsvc *tgt_addr) { if (!src_addr) { @@ -275,7 +282,7 @@ } -static void inarp_reply(VCC *vcc,unsigned long ip,struct sockaddr_atmsvc *addr) +static void inarp_reply(VCC *vcc,uint32_t ip,struct sockaddr_atmsvc *addr) { ITF *itf; @@ -403,6 +410,7 @@ VCC *vcc; int fd; + assert(entry->addr->sas_family == AF_ATMSVC); if ((fd = connect_vcc((struct sockaddr *) entry->addr,&entry->qos, CLIP_DEFAULT_IDLETIMER)) < 0) return; vcc = alloc_t(VCC); @@ -423,7 +431,7 @@ } -static void learn(VCC *vcc,unsigned long ip,struct sockaddr_atmsvc *addr) +static void learn(VCC *vcc,uint32_t ip,struct sockaddr_atmsvc *addr) { ENTRY *entry; ITF *itf; @@ -541,7 +549,7 @@ } -static void learn_nak(unsigned long ip) +static void learn_nak(uint32_t ip) { ITF *itf; ENTRY *entry; @@ -557,7 +565,7 @@ } -void need_ip(int itf_num,unsigned long ip) +void need_ip(int itf_num,uint32_t ip) { ITF *itf; ENTRY *entry; @@ -631,7 +639,7 @@ } -static unsigned long get_ip(unsigned char *ptr) +static uint32_t get_ip(unsigned char *ptr) { if (!ptr) return 0; /* awkward, but this way we avoid bus errors on architectures that @@ -646,7 +654,7 @@ ENTRY *entry; void *sha,*ssa,*spa,*tha,*tsa,*tpa; struct sockaddr_atmsvc source,target; - unsigned long src_ip,tgt_ip; + uint32_t src_ip,tgt_ip; unsigned char *here; if (len < hdr->data-(unsigned char *) hdr) { @@ -739,8 +747,8 @@ } -static int ioctl_set_pvc(ITF *itf,unsigned long ip, - struct sockaddr_atmpvc *addr,const struct atm_qos *qos,int flags) +static int ioctl_set_pvc(ITF *itf,uint32_t ip,struct sockaddr_atmpvc *addr, + const struct atm_qos *qos,int flags) { ENTRY *entry; VCC *vcc; @@ -771,8 +779,8 @@ } -static int ioctl_set_svc(ITF *itf,unsigned long ip, - struct sockaddr_atmsvc *addr,const struct atm_qos *qos,int flags) +static int ioctl_set_svc(ITF *itf,uint32_t ip,struct sockaddr_atmsvc *addr, + const struct atm_qos *qos,int flags) { ENTRY *entry; @@ -799,7 +807,7 @@ } -static int ioctl_delete(ITF *itf,unsigned long ip,int flags) +static int ioctl_delete(ITF *itf,uint32_t ip,int flags) { ENTRY *entry,*walk,*next; @@ -831,7 +839,7 @@ { ITF *itf; char buffer[MAX_ATM_ADDR_LEN+1]; - unsigned long ip; + uint32_t ip; unsigned char *ipp; diag(COMPONENT,DIAG_DEBUG,"arp_ioctl 0x%08lx",cmd); @@ -898,7 +906,7 @@ { ENTRY *entry,*next; - diag(COMPONENT,DIAG_DEBUG,"failed VCC 0x%08x",(unsigned long) vcc); + diag(COMPONENT,DIAG_DEBUG,"failed VCC 0x%p",vcc); Q_REMOVE(vcc->entry->vccs,vcc); if (!(vcc->entry->flags & ATF_ARPSRV) || vcc->entry->vccs) { /* VCC is already closed */ @@ -922,7 +930,7 @@ { ENTRY *entry; - diag(COMPONENT,DIAG_DEBUG,"connected VCC 0x%08x",(unsigned long) vcc); + diag(COMPONENT,DIAG_DEBUG,"connected VCC 0x%p",vcc); if (!vcc->connecting) diag(COMPONENT,DIAG_FATAL,"non-connecting VCC connected"); vcc->connecting = 0; @@ -942,7 +950,7 @@ { ENTRY *entry; - diag(COMPONENT,DIAG_DEBUG,"disconnected VCC0x%08x",(unsigned long) vcc); + diag(COMPONENT,DIAG_DEBUG,"disconnected VCC 0x%p",vcc); entry = vcc->entry; discard_vcc(vcc); if (entry) vcc_detach(entry); @@ -951,7 +959,7 @@ void incoming_call(VCC *vcc) { - diag(COMPONENT,DIAG_DEBUG,"incoming VCC 0x%08x",(unsigned long) vcc); + diag(COMPONENT,DIAG_DEBUG,"incoming VCC 0x%p",vcc); START_TIMER(vcc->entry,REPLY); inarp_request(vcc->entry); } diff -ur --new-file old/atm/arpd/arp.h new/atm/arpd/arp.h --- old/atm/arpd/arp.h Fri Jul 12 14:41:51 1996 +++ new/atm/arpd/arp.h Fri Feb 27 19:33:24 1998 @@ -1,18 +1,21 @@ /* arp.h - ARP state machine */ -/* Written 1995,1996 by Werner Almesberger, EPFL-LRC */ +/* Written 1995-1998 by Werner Almesberger, EPFL-LRC/ICA */ #ifndef ARP_H #define ARP_H +#include #include #include "table.h" +void discard_vccs(ENTRY *entry); void discard_entry(ENTRY *entry); -void need_ip(int itf_num,unsigned long ip); +void vcc_detach(ENTRY *entry); +void need_ip(int itf_num,uint32_t ip); void incoming_arp(VCC *vcc,struct atmarphdr *hdr,int len); int arp_ioctl(int itf_num,unsigned long cmd,struct atmarpreq *req); void vcc_connected(VCC *vcc); diff -ur --new-file old/atm/arpd/io.c new/atm/arpd/io.c --- old/atm/arpd/io.c Tue Nov 11 01:39:38 1997 +++ new/atm/arpd/io.c Fri Feb 27 19:33:40 1998 @@ -1,9 +1,10 @@ /* io.c - I/O operations */ -/* Written 1995-1997 by Werner Almesberger, EPFL-LRC */ +/* Written 1995-1998 by Werner Almesberger, EPFL-LRC/ICA */ #include +#include #include #include #include @@ -17,6 +18,7 @@ #include #include /* for CLIP_DEFAULT_IDLETIMER */ #include +#define _LINUX_NETDEVICE_H /* glibc2 */ #include #include "atm.h" @@ -122,6 +124,8 @@ case act_down: itf_down(ctrl->itf_num); break; + case act_change: + itf_change(ctrl->itf_num); case act_ioctl: ctrl->type = act_complete; ctrl->arg = arp_ioctl(ctrl->itf_num,ctrl->arg,(struct atmarpreq *) @@ -323,8 +327,7 @@ struct sockaddr_atmsvc dummy; if (!vcc->connecting) - diag(COMPONENT,DIAG_FATAL,"connecting non-connecting VCC 0x%08x", - (unsigned long) vcc); + diag(COMPONENT,DIAG_FATAL,"connecting non-connecting VCC 0x%p",vcc); memset(&dummy,0,sizeof(dummy)); if (!connect(vcc->fd,(struct sockaddr *) &dummy,sizeof(dummy))) { if (ioctl(vcc->fd,ATMARP_MKIP,CLIP_DEFAULT_IDLETIMER) < 0) { @@ -443,7 +446,7 @@ } -int ip_itf_info(int number,unsigned long *ip,unsigned long *netmask,int *mtu) +int ip_itf_info(int number,uint32_t *ip,uint32_t *netmask,int *mtu) { struct ifreq req; unsigned char *p1,*p2; diff -ur --new-file old/atm/arpd/io.h new/atm/arpd/io.h --- old/atm/arpd/io.h Thu Sep 26 16:47:02 1996 +++ new/atm/arpd/io.h Fri Feb 27 19:33:51 1998 @@ -1,11 +1,12 @@ /* io.h - I/O operations */ -/* Written 1995,1996 by Werner Almesberger, EPFL-LRC */ +/* Written 1995-1998 by Werner Almesberger, EPFL-LRC/ICA */ #ifndef IO_H #define IO_H +#include #include /* for struct sockaddr */ #include /* for struct sockaddr_atmsvc */ @@ -18,7 +19,7 @@ int set_ip(int fd,int ip); int set_encap(int fd,int mode); void send_packet(int fd,void *data,int length); -int ip_itf_info(int number,unsigned long *ip,unsigned long *netmask,int *mtu); +int ip_itf_info(int number,uint32_t *ip,uint32_t *netmask,int *mtu); int get_local(int fd,struct sockaddr_atmsvc *addr); #endif diff -ur --new-file old/atm/arpd/itf.c new/atm/arpd/itf.c --- old/atm/arpd/itf.c Tue Mar 11 21:10:08 1997 +++ new/atm/arpd/itf.c Fri Feb 27 19:34:05 1998 @@ -1,11 +1,16 @@ /* itf.c - IP interface registry */ -/* Written 1995-1997 by Werner Almesberger, EPFL-LRC */ +/* Written 1995-1998 by Werner Almesberger, EPFL-LRC/ICA */ #include +#include #include +#include #include +#include +#define _LINUX_NETDEVICE_H /* glibc2 */ +#include #include "atmd.h" @@ -28,7 +33,7 @@ } -ITF *lookup_itf_by_ip(unsigned long ip) +ITF *lookup_itf_by_ip(uint32_t ip) { ITF *itf; @@ -50,11 +55,10 @@ ITF *itf; diag(COMPONENT,DIAG_DEBUG,"ITF UP %d",number); - for (itf = itfs; itf; itf = itf->next) - if (itf->number == number) { - diag(COMPONENT,DIAG_ERROR,"interface is already active"); - return; - } + if (lookup_itf(number)) { + diag(COMPONENT,DIAG_ERROR,"interface is already active"); + return; + } itf = alloc_t(ITF); if (ip_itf_info(number,&itf->local_ip,&itf->netmask,&itf->mtu) < 0) { free(itf); @@ -71,22 +75,66 @@ } +static void itf_bring_down(ITF *itf) +{ + ENTRY *entry,*next; + + for (entry = itf->table; entry; entry = next) { + next = entry->next; + discard_entry(entry); + } + Q_REMOVE(itfs,itf); + free(itf); +} + + void itf_down(int number) { ITF *itf; - ENTRY *entry,*next; diag(COMPONENT,DIAG_DEBUG,"ITF DOWN %d",number); - for (itf = itfs; itf; itf = itf->next) - if (itf->number == number) break; + itf = lookup_itf(number); if (!itf) { diag(COMPONENT,DIAG_ERROR,"no such interface"); return; } + itf_bring_down(itf); +} + + +void itf_change(int number) +{ + ITF *itf; + ENTRY *entry,*next,*disconnected; + uint32_t local_ip,netmask; + int mtu; + + diag(COMPONENT,DIAG_DEBUG,"ITF CHANGE %d",number); + itf = lookup_itf(number); + if (!itf) { + diag(COMPONENT,DIAG_ERROR,"no such interface"); + return; + } + if (ip_itf_info(number,&local_ip,&netmask,&mtu) < 0) { + itf_bring_down(itf); + return; + } + disconnected = NULL; for (entry = itf->table; entry; entry = next) { next = entry->next; + if ((entry->flags & ATF_PERM) && + !((entry->ip ^ local_ip) & (netmask | itf->netmask))) continue; + if ((entry->flags & ATF_ARPSRV) && !((entry->ip ^ local_ip) & netmask)) + { + disconnected = entry; + discard_vccs(entry); + /* @@@ should adjust max_sdu if mtu changed */ + continue; + } discard_entry(entry); } - Q_REMOVE(itfs,itf); - free(itf); + itf->local_ip = local_ip; + itf->netmask = netmask; + itf->mtu = mtu; + if (disconnected) vcc_detach(disconnected); } diff -ur --new-file old/atm/arpd/itf.h new/atm/arpd/itf.h --- old/atm/arpd/itf.h Wed Dec 13 10:26:24 1995 +++ new/atm/arpd/itf.h Fri Feb 27 19:34:11 1998 @@ -1,17 +1,20 @@ /* itf.h - IP interface registry */ -/* Written 1995 by Werner Almesberger, EPFL-LRC */ +/* Written 1995-1998 by Werner Almesberger, EPFL-LRC/ICA */ #ifndef ITF_H #define ITF_H +#include + #include "table.h" ITF *lookup_itf(int number); -ITF *lookup_itf_by_ip(unsigned long ip); +ITF *lookup_itf_by_ip(uint32_t ip); int itf_create(int number); void itf_up(int number); void itf_down(int number); +void itf_change(int number); #endif diff -ur --new-file old/atm/arpd/table.c new/atm/arpd/table.c --- old/atm/arpd/table.c Tue Nov 11 01:17:08 1997 +++ new/atm/arpd/table.c Fri Feb 27 19:34:23 1998 @@ -1,9 +1,10 @@ /* table.c - ATMARP table */ -/* Written 1995-1997 by Werner Almesberger, EPFL-LRC */ +/* Written 1995-1998 by Werner Almesberger, EPFL-LRC/ICA */ #include +#include #include #include #include @@ -40,7 +41,7 @@ } -ENTRY *lookup_ip(const ITF *itf,unsigned long ip) +ENTRY *lookup_ip(const ITF *itf,uint32_t ip) { ENTRY *walk; diff -ur --new-file old/atm/arpd/table.h new/atm/arpd/table.h --- old/atm/arpd/table.h Mon Jan 13 21:03:08 1997 +++ new/atm/arpd/table.h Fri Feb 27 19:34:46 1998 @@ -1,11 +1,12 @@ /* table.h - ATMARP table */ -/* Written 1995-1997 by Werner Almesberger, EPFL-LRC */ +/* Written 1995-1998 by Werner Almesberger, EPFL-LRC/ICA */ #ifndef TABLE_H #define TABLE_H +#include #include #include "atmd.h" @@ -34,7 +35,7 @@ typedef struct _entry { ADDR_STATE state; int svc; - unsigned long ip; + uint32_t ip; struct sockaddr_atmsvc *addr; /* NULL if none */ struct atm_qos qos; int flags; @@ -47,8 +48,8 @@ } ENTRY; typedef struct _itf { - unsigned long local_ip; /* @@@ */ - unsigned long netmask; + uint32_t local_ip; /* @@@ */ + uint32_t netmask; int number; int mtu; struct atm_qos qos; /* default QOS */ @@ -75,7 +76,7 @@ ENTRY *alloc_entry(int svc); -ENTRY *lookup_ip(const ITF *itf,unsigned long ip); +ENTRY *lookup_ip(const ITF *itf,uint32_t ip); ENTRY *lookup_addr(const ITF *itf,const struct sockaddr_atmsvc *addr); ENTRY *lookup_incoming(const struct sockaddr_atmsvc *addr); diff -ur --new-file old/atm/atm.patch new/atm/atm.patch --- old/atm/atm.patch Wed Nov 19 03:57:15 1997 +++ new/atm/atm.patch Fri Mar 13 22:27:46 1998 @@ -1,5 +1,5 @@ ---- ref/Makefile Wed Nov 19 00:38:01 1997 -+++ work/Makefile Wed Nov 19 00:36:59 1997 +--- ref/Makefile Mon Jan 12 23:47:55 1998 ++++ work/Makefile Fri Mar 13 23:28:28 1998 @@ -129,6 +129,10 @@ DRIVERS := $(DRIVERS) drivers/net/net.a @@ -11,19 +11,19 @@ ifeq ($(CONFIG_SCSI),y) DRIVERS := $(DRIVERS) drivers/scsi/scsi.a endif -@@ -310,6 +314,7 @@ +@@ -317,6 +321,7 @@ + if [ -f NET_MODULES ]; then inst_mod NET_MODULES net; fi; \ + if [ -f IPV4_MODULES ]; then inst_mod IPV4_MODULES ipv4; fi; \ + if [ -f IPV6_MODULES ]; then inst_mod IPV6_MODULES ipv6; fi; \ ++ if [ -f ATM_MODULES ]; then inst_mod ATM_MODULES atm; fi; \ + if [ -f SCSI_MODULES ]; then inst_mod SCSI_MODULES scsi; fi; \ if [ -f FS_MODULES ]; then inst_mod FS_MODULES fs; fi; \ if [ -f NLS_MODULES ]; then inst_mod NLS_MODULES fs; fi; \ - if [ -f CDROM_MODULES ]; then inst_mod CDROM_MODULES cdrom; fi; \ -+ if [ -f ATM_MODULES ]; then inst_mod ATM_MODULES atm; fi; \ - \ - ls *.o > .allmods; \ - echo $$MODULES | tr ' ' '\n' | sort | comm -23 .allmods - > .misc; \ ---- ref/Documentation/Configure.help Thu Nov 13 21:56:48 1997 -+++ work/Documentation/Configure.help Wed Nov 19 00:36:59 1997 -@@ -1636,6 +1636,79 @@ - you can read some network related routing information from that - file. Everything you write to that file will be discarded. +--- ref/Documentation/Configure.help Mon Jan 12 23:46:16 1998 ++++ work/Documentation/Configure.help Thu Jan 15 22:49:10 1998 +@@ -2191,6 +2191,79 @@ + This is a backward compatibility option, choose Y for now. + This option will be removed soon. +Asynchronous Transfer Mode (ATM) +CONFIG_ATM @@ -102,15 +102,15 @@ CONFIG_SCSI If you want to use a SCSI harddisk, SCSI tapedrive, SCSI CDROM or --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/Documentation/atm.txt Wed Nov 19 00:36:59 1997 ++++ work/Documentation/atm.txt Thu Jan 15 22:49:10 1998 @@ -0,0 +1,4 @@ +In order to use anything but the most primitive functions of ATM, +several user-mode programs are required to assist the kernel. These +programs and related material can be found via the ATM on Linux Web +page at http://lrcwww.epfl.ch/linux-atm/ ---- ref/arch/i386/config.in Thu Oct 30 00:34:54 1997 -+++ work/arch/i386/config.in Wed Nov 19 00:36:59 1997 -@@ -80,6 +80,9 @@ +--- ref/arch/i386/config.in Mon Jan 5 09:06:25 1998 ++++ work/arch/i386/config.in Thu Jan 15 22:49:10 1998 +@@ -84,6 +84,9 @@ bool 'Network device support' CONFIG_NETDEVICES if [ "$CONFIG_NETDEVICES" = "y" ]; then source drivers/net/Config.in @@ -120,8 +120,8 @@ fi endmenu fi ---- ref/drivers/Makefile Sat Aug 16 18:53:08 1997 -+++ work/drivers/Makefile Wed Nov 19 00:36:59 1997 +--- ref/drivers/Makefile Thu Dec 4 00:17:30 1997 ++++ work/drivers/Makefile Thu Jan 15 22:49:10 1998 @@ -9,7 +9,7 @@ SUB_DIRS := block char net misc #streams @@ -144,7 +144,7 @@ ifeq ($(CONFIG_AP1000),y) --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/drivers/atm/Config.in Wed Nov 19 00:36:59 1997 ++++ work/drivers/atm/Config.in Thu Jan 15 22:49:10 1998 @@ -0,0 +1,23 @@ +# +# ATM device configuration @@ -170,7 +170,7 @@ +# tristate 'IDT 77201 (NICStAR)' CONFIG_ATM_NICSTAR y +fi --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/drivers/atm/Makefile Wed Nov 19 00:36:59 1997 ++++ work/drivers/atm/Makefile Thu Jan 15 22:49:10 1998 @@ -0,0 +1,57 @@ +# File: drivers/atm/Makefile +# @@ -230,7 +230,7 @@ + +include $(TOPDIR)/Rules.make --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/drivers/atm/atmdev_init.c Wed Nov 19 00:36:59 1997 ++++ work/drivers/atm/atmdev_init.c Thu Jan 15 22:49:10 1998 @@ -0,0 +1,48 @@ +/* drivers/atm/atmdev_init.c - ATM device driver initialization */ + @@ -281,11 +281,11 @@ + return devs; +} --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/drivers/atm/atmtcp.c Wed Nov 19 00:36:59 1997 -@@ -0,0 +1,228 @@ ++++ work/drivers/atm/atmtcp.c Thu Feb 12 17:46:28 1998 +@@ -0,0 +1,226 @@ +/* drivers/atm/atmtcp.c - ATM over TCP "device" driver */ + -+/* Written 1997 by Werner Almesberger, EPFL LRC */ ++/* Written 1997,1998 by Werner Almesberger, EPFL LRC/ICA */ + + +#include @@ -332,11 +332,9 @@ +{ + struct atm_cirange ci; + struct atm_vcc *vcc; -+ int error; + + if (cmd != ATM_SETCIRANGE) return -EINVAL; -+ error = copy_from_user(&ci,(void *) arg,sizeof(ci)); -+ if (error) return error; ++ if (copy_from_user(&ci,(void *) arg,sizeof(ci))) return -EFAULT; + if (ci.vpi_bits == ATM_CI_MAX) ci.vpi_bits = MAX_VPI_BITS; + if (ci.vci_bits == ATM_CI_MAX) ci.vci_bits = MAX_VCI_BITS; + if (ci.vpi_bits > MAX_VPI_BITS || ci.vpi_bits < 0 || @@ -512,14 +510,15 @@ + return dev->number; +} --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/drivers/atm/eni.c Wed Nov 19 00:36:59 1997 -@@ -0,0 +1,2088 @@ ++++ work/drivers/atm/eni.c Mon Mar 9 22:29:00 1998 +@@ -0,0 +1,2148 @@ +/* drivers/atm/eni.c - Efficient Networks ENI155P device driver */ + -+/* Written 1995-1997 by Werner Almesberger, EPFL LRC */ ++/* Written 1995-1998 by Werner Almesberger, EPFL LRC/ICA */ + + +#include ++#include +#include +#include +#include @@ -1700,12 +1699,14 @@ + struct eni_vcc *eni_vcc = ENI_VCC(vcc); + struct eni_tx *tx; + unsigned long size,mem; -+ int rate,unlimited,new_tx; ++ int rate,ubr,unlimited,new_tx; + int pre,res,order; + int error; + + rate = atm_pcr_goal(txtp); -+ unlimited = txtp->traffic_class == ATM_UBR && !rate; ++ ubr = txtp->traffic_class == ATM_UBR; ++ unlimited = ubr && (!rate || rate <= -ATM_OC3_PCR || ++ rate >= ATM_OC3_PCR); + if (!unlimited) size = txtp->max_sdu*3; /* @@@ improve */ + else { + if (eni_dev->ubr) { @@ -1731,8 +1732,7 @@ + tx->send = (u32 *) mem; + tx->words = size >> 2; + skb_queue_head_init(&tx->backlog); -+ size >>= 10; -+ for (order = -1; size; order++) size >>= 1; ++ for (order = 0; size > (1 << (order+10)); order++); + writel((order << MID_SIZE_SHIFT) | + ((tx->send-eni_dev->ram) >> MID_LOC_SKIP), + eni_dev->reg+MID_TX_PLACE(tx->index)); @@ -1743,10 +1743,12 @@ + if (!error && txtp->min_pcr > rate) error = -EINVAL; + if (!error && txtp->max_pcr && txtp->max_pcr != ATM_MAX_PCR && + txtp->max_pcr < rate) error = -EINVAL; -+ if (!error && txtp->traffic_class != ATM_UBR && -+ rate > eni_dev->tx_bw+tx->reserved) error = -EINVAL; -+ if (!error && set_rsv && rate < tx->shaping) error = -EINVAL; -+ if (!error && !set_rsv && rate > tx->shaping) error = -EINVAL; ++ if (!error && !ubr && rate > eni_dev->tx_bw+tx->reserved) ++ error = -EINVAL; ++ if (!error && set_rsv && !set_shp && rate < tx->shaping) ++ error = -EINVAL; ++ if (!error && !set_rsv && rate > tx->reserved && !ubr) ++ error = -EINVAL; + if (error) { + if (new_tx) { + tx->send = NULL; @@ -1755,7 +1757,7 @@ + return error; + } + txtp->pcr = rate; -+ if (!unlimited && set_rsv) { ++ if (set_rsv && !ubr) { + eni_dev->tx_bw += tx->reserved; + tx->reserved = rate; + eni_dev->tx_bw -= rate; @@ -2402,18 +2404,17 @@ + +static int eni_ioctl(struct atm_dev *dev,unsigned int cmd,void *arg) +{ -+ int error; -+ + if (cmd == ENI_MEMDUMP) { ++ printk(KERN_WARNING "Please use /proc/atm/" DEV_LABEL ":%d " ++ "instead of obsolete ioctl ENI_MEMDUMP\n",dev->number); + dump(dev); + return 0; + } + if (cmd == ATM_SETCIRANGE) { + struct atm_cirange ci; + -+ error = copy_from_user(&ci,(void *) arg, -+ sizeof(struct atm_cirange)); -+ if (error) return error; ++ if (copy_from_user(&ci,(void *) arg,sizeof(struct atm_cirange))) ++ return -EFAULT; + if ((ci.vpi_bits == 0 || ci.vpi_bits == ATM_CI_MAX) && + (ci.vci_bits == NR_VCI_LD || ci.vpi_bits == ATM_CI_MAX)) + return 0; @@ -2441,7 +2442,7 @@ + if (level == SOL_AAL && (optname == SO_BCTXOPT || + optname == SO_BCRXOPT)) + return copy_to_user(optval,optname == SO_BCTXOPT ? &bctx : -+ &bcrx,sizeof(struct atm_buffconst)); ++ &bcrx,sizeof(struct atm_buffconst)) ? -EFAULT : 0; + return -EINVAL; +} + @@ -2510,6 +2511,62 @@ +} + + ++static int eni_proc_read(struct atm_dev *dev,loff_t *pos,char *page) ++{ ++ static const char *signal[] = { "LOST","unknown","okay" }; ++ struct eni_dev *eni_dev = ENI_DEV(dev); ++ struct atm_vcc *vcc; ++ int left,i; ++ ++ left = *pos; ++ if (!left) ++ return sprintf(page,DEV_LABEL "(itf %d) signal %s, %dkB, " ++ "%d cps remaining\n",dev->number,signal[(int) dev->signal], ++ eni_dev->mem >> 10,eni_dev->tx_bw); ++ for (i = 0; i < NR_CHAN; i++) { ++ struct eni_tx *tx = eni_dev->tx+i; ++ ++ if (!tx->send) continue; ++ if (--left) continue; ++ return sprintf(page,"tx[%d]: 0x%06x-0x%06lx (%6ld bytes), " ++ "rsv %d cps, shp %d cps%s\n",i,(tx->send-eni_dev->ram)*4, ++ (tx->send-eni_dev->ram+tx->words)*4-1,tx->words*4, ++ tx->reserved,tx->shaping, ++ tx == eni_dev->ubr ? " (UBR)" : ""); ++ } ++ for (vcc = dev->vccs; vcc; vcc = vcc->next) { ++ struct eni_vcc *eni_vcc = ENI_VCC(vcc); ++ int length; ++ ++ if (--left) continue; ++ length = sprintf(page,"vcc %4d: ",vcc->vci); ++ if (eni_vcc->rx) { ++ length += sprintf(page+length,"0x%06x-0x%06lx " ++ "(%6ld bytes)",(eni_vcc->recv-eni_dev->ram)*4, ++ (eni_vcc->recv-eni_dev->ram+eni_vcc->words)*4-1, ++ eni_vcc->words*4); ++ if (eni_vcc->tx) length += sprintf(page+length,", "); ++ } ++ if (eni_vcc->tx) ++ length += sprintf(page+length,"tx[%d]", ++ eni_vcc->tx->index); ++ page[length] = '\n'; ++ return length+1; ++ } ++ for (i = 0; i < eni_dev->free_len; i++) { ++ struct eni_free *fe = eni_dev->free_list+i; ++ unsigned long offset; ++ ++ if (--left) continue; ++ offset = (unsigned long) eni_dev->ram+eni_dev->base_diff; ++ return sprintf(page,"free 0x%06lx-0x%06lx (%6d bytes)\n", ++ fe->start-offset,fe->start-offset+(1 << fe->order)-1, ++ 1 << fe->order); ++ } ++ return 0; ++} ++ ++ +static const struct atmdev_ops ops = { + NULL, /* no dev_close */ + eni_open, @@ -2524,7 +2581,8 @@ + eni_phy_get, + NULL, /* no feedback */ + eni_change_qos, /* no change_qos */ -+ NULL /* no free_rx_skb */ ++ NULL, /* no free_rx_skb */ ++ eni_proc_read +}; + + @@ -2603,7 +2661,7 @@ + +#endif --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/drivers/atm/eni.h Wed Nov 19 00:41:23 1997 ++++ work/drivers/atm/eni.h Fri Mar 13 19:59:47 1998 @@ -0,0 +1,105 @@ +/* drivers/atm/eni.h - Efficient Networks ENI155P device driver declarations */ + @@ -2711,7 +2769,7 @@ + +#endif --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/drivers/atm/midway.h Wed Nov 19 00:36:59 1997 ++++ work/drivers/atm/midway.h Thu Jan 15 22:49:10 1998 @@ -0,0 +1,265 @@ +/* drivers/atm/midway.h - Efficient Networks Midway (SAR) description */ + @@ -2979,11 +3037,11 @@ + +#endif --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/drivers/atm/suni.c Wed Nov 19 00:36:59 1997 -@@ -0,0 +1,289 @@ ++++ work/drivers/atm/suni.c Fri Mar 6 14:38:40 1998 +@@ -0,0 +1,301 @@ +/* drivers/atm/suni.c - PMC SUNI (PHY) driver */ + -+/* Written 1995-1997 by Werner Almesberger, EPFL LRC */ ++/* Written 1995-1998 by Werner Almesberger, EPFL LRC/ICA */ + + +#include @@ -3092,10 +3150,10 @@ + if (arg) + error = copy_to_user(arg,&PRIV(dev)->sonet_stats, + sizeof(struct sonet_stats)); -+ if (zero) ++ if (zero && !error) + memset(&PRIV(dev)->sonet_stats,0,sizeof(struct sonet_stats)); + restore_flags(flags); -+ return error; ++ return error ? -EFAULT : 0; +} + + @@ -3109,10 +3167,9 @@ + +static int change_diag(struct atm_dev *dev,void *arg,int set) +{ -+ int error,todo; ++ int todo; + -+ error = get_user(todo,(int *) arg); -+ if (error) return error; ++ if (get_user(todo,(int *) arg)) return -EFAULT; + HANDLE_FLAG(SONET_INS_SBIP,TSOP_DIAG,SUNI_TSOP_DIAG_DBIP8); + HANDLE_FLAG(SONET_INS_LBIP,TLOP_DIAG,SUNI_TLOP_DIAG_DBIP); + HANDLE_FLAG(SONET_INS_PBIP,TPOP_CD,SUNI_TPOP_DIAG_DB3); @@ -3121,7 +3178,7 @@ + HANDLE_FLAG(SONET_INS_PAIS,TPOP_CD,SUNI_TPOP_DIAG_PAIS); + HANDLE_FLAG(SONET_INS_LOS,TSOP_DIAG,SUNI_TSOP_DIAG_DLOS); + HANDLE_FLAG(SONET_INS_HCS,TACP_CS,SUNI_TACP_CS_DHCS); -+ return put_user(todo,(int *) arg); ++ return put_user(todo,(int *) arg) ? -EFAULT : 0; +} + + @@ -3141,7 +3198,7 @@ + if (GET(TPOP_CD) & SUNI_TPOP_DIAG_PAIS) set |= SONET_INS_PAIS; + if (GET(TSOP_DIAG) & SUNI_TSOP_DIAG_DLOS) set |= SONET_INS_LOS; + if (GET(TACP_CS) & SUNI_TACP_CS_DHCS) set |= SONET_INS_HCS; -+ return put_user(set,(int *) arg); ++ return put_user(set,(int *) arg) ? -EFAULT : 0; +} + + @@ -3163,7 +3220,8 @@ + if (arg != SONET_FRAME_SONET) return -EINVAL; + return 0; + case SONET_GETFRAMING: -+ return put_user(SONET_FRAME_SONET,(int *) arg); ++ return put_user(SONET_FRAME_SONET,(int *) arg) ? ++ -EFAULT : 0; + case SONET_GETFRSENSE: + return -EINVAL; + case SUNI_SETLOOP: @@ -3176,17 +3234,26 @@ + PRIV(dev)->loop_mode = (int) arg; + return 0; + case SUNI_GETLOOP: -+ return put_user(PRIV(dev)->loop_mode,(int *) arg); ++ return put_user(PRIV(dev)->loop_mode,(int *) arg) ? ++ -EFAULT : 0; + default: + return -EINVAL; + } +} + + ++static void poll_los(struct atm_dev *dev) ++{ ++ dev->signal = GET(RSOP_SIS) & SUNI_RSOP_SIS_LOSV ? ATM_PHY_SIG_LOST : ++ ATM_PHY_SIG_FOUND; ++} ++ ++ +static void suni_int(struct atm_dev *dev) +{ ++ poll_los(dev); + printk(KERN_NOTICE "%s(itf %d): signal %s\n",dev->type,dev->number, -+ GET(RSOP_SIS) & SUNI_RSOP_SIS_LOSV ? "lost" : "detected again"); ++ dev->signal == ATM_PHY_SIG_LOST ? "lost" : "detected again"); +} + + @@ -3205,7 +3272,10 @@ + memset(&PRIV(dev)->sonet_stats,0,sizeof(struct sonet_stats)); + PUT(GET(RSOP_CIE) | SUNI_RSOP_CIE_LOSE,RSOP_CIE); + /* interrupt on loss of signal */ -+ (void) GET(RSOP_SIS); /* clear SUNI interrupts */ ++ poll_los(dev); /* ... and clear SUNI interrupts */ ++ if (dev->signal == ATM_PHY_SIG_LOST) ++ printk(KERN_WARNING "%s(itf %d): no signal\n",dev->type, ++ dev->number); + PRIV(dev)->loop_mode = SUNI_LM_NONE; + suni_hz(0); /* clear SUNI counters */ + (void) fetch_stats(dev,NULL,1); /* clear kernel counters */ @@ -3271,7 +3341,7 @@ + +#endif --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/drivers/atm/suni.h Wed Nov 19 00:41:22 1997 ++++ work/drivers/atm/suni.h Fri Mar 13 19:59:44 1998 @@ -0,0 +1,219 @@ +/* drivers/atm/suni.h - PMC SUNI (PHY) declarations */ + @@ -3493,7 +3563,7 @@ + +#endif --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/drivers/atm/tonga.h Wed Nov 19 00:36:59 1997 ++++ work/drivers/atm/tonga.h Thu Jan 15 22:49:10 1998 @@ -0,0 +1,20 @@ +/* drivers/atm/tonga.h - Efficient Networks Tonga (PCI bridge) declarations */ + @@ -3516,7 +3586,7 @@ + +#endif --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/drivers/atm/uPD98401.h Wed Nov 19 00:36:59 1997 ++++ work/drivers/atm/uPD98401.h Thu Jan 15 22:49:10 1998 @@ -0,0 +1,292 @@ +/* drivers/atm/uPD98401.h - NEC uPD98401 (SAR) declarations */ + @@ -3811,11 +3881,11 @@ + +#endif --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/drivers/atm/uPD98402.c Wed Nov 19 00:36:59 1997 -@@ -0,0 +1,225 @@ ++++ work/drivers/atm/uPD98402.c Thu Feb 12 17:44:52 1998 +@@ -0,0 +1,224 @@ +/* drivers/atm/uPD98402.c - NEC uPD98402 (PHY) declarations */ + -+/* Written 1995-1997 by Werner Almesberger, EPFL LRC */ ++/* Written 1995-1998 by Werner Almesberger, EPFL LRC/ICA */ + + +#include @@ -3860,16 +3930,16 @@ + cli(); + PRIV(dev)->sonet_stats.uncorr_hcs += GET(HECCT); + if (arg) -+ error = copy_to_user (arg,&PRIV(dev)->sonet_stats, ++ error = copy_to_user(arg,&PRIV(dev)->sonet_stats, + sizeof(struct sonet_stats)); -+ if (zero) { ++ if (zero && !error) { + memset(&PRIV(dev)->sonet_stats,0,sizeof(struct sonet_stats)); + PRIV(dev)->sonet_stats.corr_hcs = -1; + PRIV(dev)->sonet_stats.tx_cells = -1; + PRIV(dev)->sonet_stats.rx_cells = -1; + } + restore_flags(flags); -+ return error; ++ return error ? -EFAULT : 0; +} + + @@ -3909,14 +3979,12 @@ + + save_flags(flags); + cli(); -+ error = put_user(GET(C11R),arg); -+ if (!error) error = put_user(GET(C12R),arg+1); -+ if (!error) error = put_user(GET(C13R),arg+2); ++ error = put_user(GET(C11R),arg) || put_user(GET(C12R),arg+1) || ++ put_user(GET(C13R),arg+2); + restore_flags(flags); -+ if (!error) error = put_user(0xff,arg+3); -+ if (!error) error = put_user(0xff,arg+4); -+ if (!error) error = put_user(0xff,arg+5); -+ return error; ++ error = error || put_user(0xff,arg+3) || put_user(0xff,arg+4) || ++ put_user(0xff,arg+5); ++ return error ? -EFAULT : 0; +} + + @@ -3931,7 +3999,8 @@ + case SONET_SETFRAMING: + return set_framing(dev,(int) arg); + case SONET_GETFRAMING: -+ return put_user(PRIV(dev)->framing,(int *) arg); ++ return put_user(PRIV(dev)->framing,(int *) arg) ? ++ -EFAULT : 0; + case SONET_GETFRSENSE: + return get_sense(dev,arg); + default: @@ -4039,7 +4108,7 @@ + +#endif --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/drivers/atm/uPD98402.h Wed Nov 19 00:36:59 1997 ++++ work/drivers/atm/uPD98402.h Thu Jan 15 22:49:10 1998 @@ -0,0 +1,106 @@ +/* drivers/atm/uPD98402.h - NEC uPD98402 (PHY) declarations */ + @@ -4148,11 +4217,11 @@ + +#endif --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/drivers/atm/zatm.c Wed Nov 19 00:36:59 1997 -@@ -0,0 +1,1862 @@ ++++ work/drivers/atm/zatm.c Fri Mar 6 21:32:07 1998 +@@ -0,0 +1,1871 @@ +/* drivers/atm/zatm.c - ZeitNet ZN122x device driver */ + -+/* Written 1995-1997 by Werner Almesberger, EPFL LRC */ ++/* Written 1995-1998 by Werner Almesberger, EPFL LRC/ICA */ + + +#include @@ -4369,9 +4438,9 @@ + skb_reserve(skb,(unsigned char *) ((((unsigned long) skb->data+ + align+offset-1) & ~(align-1))-offset)-skb->data); + head = (struct rx_buffer_head *) skb->data; ++ skb_reserve(skb,sizeof(struct rx_buffer_head)); + if (!first) first = head; + count++; -+ skb->data += sizeof(struct rx_buffer_head); + head->buffer = virt_to_bus(skb->data); + head->link = 0; + head->skb = skb; @@ -4476,11 +4545,13 @@ + cli(); + if (!offset || pool->offset == offset) { + pool->next_cnt = 0; ++ restore_flags(flags); + return; + } + if (offset != pool->next_off) { + pool->next_off = offset; + pool->next_cnt = 0; ++ restore_flags(flags); + return; + } + if (++pool->next_cnt >= pool->next_thres) { @@ -4878,6 +4949,9 @@ + zpokel(zatm_dev,(zpeekl(zatm_dev,pos) & ~(0xffff << shift)) | + ((zatm_vcc->rx_chan | uPD98401_RXLT_ENBL) << shift),pos); + restore_flags(flags); ++/* Ugly hack to ensure that ttcp_atm will work with the current allocation ++ scheme. @@@ */ ++if (vcc->rx_quota < 200000) vcc->rx_quota = 200000; + return 0; +} + @@ -5101,6 +5175,10 @@ +} + + ++/* ++ * BUG BUG BUG: Doesn't handle "new-style" rate specification yet. ++ */ ++ +static int alloc_shaper(struct atm_dev *dev,int *pcr,int min,int max,int ubr) +{ + struct zatm_dev *zatm_dev; @@ -5288,7 +5366,7 @@ + loop = zatm_vcc->ring+RING_ENTRIES*RING_WORDS; + loop[0] = uPD98401_TXPD_V; + loop[1] = loop[2] = 0; -+ loop[3] = (unsigned long) zatm_vcc->ring; ++ loop[3] = virt_to_bus(zatm_vcc->ring); + zatm_vcc->ring_curr = 0; + zatm_vcc->txing = 0; + skb_queue_head_init(&zatm_vcc->backlog); @@ -5750,7 +5828,6 @@ +{ + struct zatm_dev *zatm_dev; + unsigned long flags; -+ int error; + + zatm_dev = ZATM_DEV(dev); + switch (cmd) { @@ -5762,9 +5839,9 @@ + struct zatm_pool_info info; + int pool; + -+ error = get_user(pool, -+ &((struct zatm_pool_req *) arg)->pool_num); -+ if (error) return error; ++ if (get_user(pool, ++ &((struct zatm_pool_req *) arg)->pool_num)) ++ return -EFAULT; + if (pool < 0 || pool > ZATM_LAST_POOL) + return -EINVAL; + save_flags(flags); @@ -5775,10 +5852,9 @@ + zatm_dev->pool_info[pool].rqu_count = 0; + } + restore_flags(flags); -+ error = copy_to_user( ++ return copy_to_user( + &((struct zatm_pool_req *) arg)->info, -+ &info,sizeof(info)); -+ return error; ++ &info,sizeof(info)) ? -EFAULT : 0; + } + case ZATM_SETPOOL: + { @@ -5786,15 +5862,14 @@ + int pool; + + if (!suser()) return -EPERM; -+ error = get_user(pool, -+ &((struct zatm_pool_req *) arg)->pool_num); -+ if (error) return error; ++ if (get_user(pool, ++ &((struct zatm_pool_req *) arg)->pool_num)) ++ return -EFAULT; + if (pool < 0 || pool > ZATM_LAST_POOL) + return -EINVAL; -+ error = copy_from_user(&info, ++ if (copy_from_user(&info, + &((struct zatm_pool_req *) arg)->info, -+ sizeof(info)); -+ if (error) return error; ++ sizeof(info))) return -EFAULT; + if (!info.low_water) + info.low_water = zatm_dev-> + pool_info[pool].low_water; @@ -5826,16 +5901,18 @@ + save_flags(flags); + cli(); + for (i = 0; i < ZATM_TIMER_HISTORY_SIZE; i++) { -+ error = copy_to_user( ++ if (!copy_to_user( + (struct zatm_t_hist *) arg+i, + &zatm_dev->timer_history[ + (zatm_dev->th_curr+i) & + (ZATM_TIMER_HISTORY_SIZE-1)], -+ sizeof(struct zatm_t_hist)); -+ if (error) break; ++ sizeof(struct zatm_t_hist))) ++ continue; ++ restore_flags(flags); ++ return -EFAULT; + } + restore_flags(flags); -+ return error; ++ return 0; + } +#endif + default: @@ -5862,7 +5939,7 @@ + if (level == SOL_AAL && (optname == SO_BCTXOPT || + optname == SO_BCRXOPT)) + return copy_to_user(optval,optname == SO_BCTXOPT ? &bctx : -+ &bcrx,sizeof(struct atm_buffconst)); ++ &bcrx,sizeof(struct atm_buffconst)) ? -EFAULT : 0; + return -EINVAL; +} + @@ -5946,7 +6023,8 @@ + zatm_phy_get, + zatm_feedback, + zatm_change_qos, -+ NULL /* no free_rx_skb */ ++ NULL, /* no free_rx_skb */ ++ NULL /* no proc_read */ +}; + + @@ -6013,7 +6091,7 @@ + +#endif --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/drivers/atm/zatm.h Wed Nov 19 00:41:27 1997 ++++ work/drivers/atm/zatm.h Fri Mar 13 19:59:50 1998 @@ -0,0 +1,129 @@ +/* drivers/atm/zatm.h - ZeitNet ZN122x device driver declarations */ + @@ -6145,7 +6223,7 @@ + +#endif --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/drivers/atm/zeprom.h Wed Nov 19 00:36:59 1997 ++++ work/drivers/atm/zeprom.h Thu Jan 15 22:49:10 1998 @@ -0,0 +1,34 @@ +/* drivers/atm/zeprom.h - ZeitNet ZN122x EEPROM (NM93C46) declarations */ + @@ -6181,8 +6259,8 @@ +/* No other commands are needed. */ + +#endif ---- ref/drivers/block/genhd.c Sat Aug 16 18:53:08 1997 -+++ work/drivers/block/genhd.c Wed Nov 19 00:36:59 1997 +--- ref/drivers/block/genhd.c Sun Jan 4 19:40:15 1998 ++++ work/drivers/block/genhd.c Thu Jan 15 22:49:10 1998 @@ -58,6 +58,7 @@ extern int blk_dev_init(void); extern int scsi_dev_init(void); @@ -6191,7 +6269,7 @@ /* * disk_name() is used by genhd.c and md.c. -@@ -1054,6 +1055,9 @@ +@@ -1106,6 +1107,9 @@ #endif #ifdef CONFIG_INET net_dev_init(); @@ -6201,49 +6279,8 @@ #endif #ifdef CONFIG_VT console_map_init(); ---- ref/fs/proc/root.c Sun Oct 12 19:16:37 1997 -+++ work/fs/proc/root.c Wed Nov 19 00:36:59 1997 -@@ -18,6 +18,10 @@ - #include - #endif - -+ -+extern void atm_proc_init(void); -+ -+ - /* - * Offset of the first process in the /proc root directory.. - */ -@@ -315,6 +319,16 @@ - return PROC_DYNAMIC_FIRST + i; - } - -+struct proc_dir_entry proc_atm = { -+ PROC_ATM, 3, "atm", -+ S_IFDIR | S_IRUGO | S_IXUGO, 2, 0, 0, -+ 0, &proc_dir_inode_operations, -+ NULL, NULL, -+ NULL, -+ &proc_root, NULL -+}; -+ -+ - int proc_register(struct proc_dir_entry * dir, struct proc_dir_entry * dp) - { - int i; -@@ -602,6 +616,10 @@ - proc_scsi = create_proc_entry("scsi", S_IFDIR, 0); - #ifdef CONFIG_SYSCTL - proc_register(&proc_root, &proc_sys_root); -+#endif -+#ifdef CONFIG_ATM -+ proc_register(&proc_root, &proc_atm); -+ atm_proc_init(); - #endif - #ifdef CONFIG_MCA - proc_register(&proc_root, &proc_mca); --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/include/linux/arequipa.h Wed Nov 19 00:44:35 1997 ++++ work/include/linux/arequipa.h Fri Mar 6 12:20:36 1998 @@ -0,0 +1,63 @@ +/* arequipa.h - Arequipa interface definitions */ + @@ -6309,8 +6346,8 @@ + +#endif --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/include/linux/atm.h Wed Nov 19 00:36:59 1997 -@@ -0,0 +1,248 @@ ++++ work/include/linux/atm.h Fri Mar 6 12:20:09 1998 +@@ -0,0 +1,254 @@ +/* atm.h - general ATM declarations */ + +/* Written 1995-1997 by Werner Almesberger, EPFL LRC */ @@ -6532,6 +6569,12 @@ +} + + ++static __inline__ int atmpvc_addr_in_use(struct sockaddr_atmpvc addr) ++{ ++ return addr.sap_addr.itf || addr.sap_addr.vpi || addr.sap_addr.vci; ++} ++ ++ +/* + * Some stuff for linux/sockios.h + */ @@ -6560,7 +6603,7 @@ + +#endif --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/include/linux/atm_eni.h Wed Nov 19 00:36:59 1997 ++++ work/include/linux/atm_eni.h Thu Jan 15 22:49:10 1998 @@ -0,0 +1,15 @@ +/* atm_eni.h - Driver-specific declarations of the ENI driver (for use by + driver-specific utilities) */ @@ -6578,7 +6621,7 @@ + +#endif --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/include/linux/atm_tcp.h Wed Nov 19 00:36:59 1997 ++++ work/include/linux/atm_tcp.h Thu Jan 15 22:49:10 1998 @@ -0,0 +1,30 @@ +/* atm_tcp.h - Driver-specific declarations of the ATMTCP driver (for use by + driver-specific utilities) */ @@ -6611,7 +6654,7 @@ + +#endif --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/include/linux/atm_zatm.h Wed Nov 19 00:36:59 1997 ++++ work/include/linux/atm_zatm.h Thu Jan 15 22:49:10 1998 @@ -0,0 +1,54 @@ +/* atm_zatm.h - Driver-specific declarations of the ZATM driver (for use by + driver-specific utilities) */ @@ -6668,17 +6711,22 @@ + +#endif --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/include/linux/atmarp.h Wed Nov 19 00:36:59 1997 -@@ -0,0 +1,98 @@ ++++ work/include/linux/atmarp.h Fri Mar 6 12:20:30 1998 +@@ -0,0 +1,104 @@ +/* atmarp.h - ATM ARP protocol and kernel-demon interface definitions */ + -+/* Written 1995-1997 by Werner Almesberger, EPFL LRC */ ++/* Written 1995-1998 by Werner Almesberger, EPFL LRC/ICA */ + + +#ifndef _LINUX_ATMARP_H +#define _LINUX_ATMARP_H + ++#ifdef __KERNEL__ /* @@@ glibc2 hack */ +#include ++#else ++#include ++#endif ++ +#include +#include + @@ -6755,7 +6803,8 @@ + act_up, /* interface is coming up */ + act_down, /* interface is going down */ + act_ioctl, /* ioctl follows */ -+ act_complete /* demon indicates completion */ ++ act_complete, /* demon indicates completion */ ++ act_change /* interface configuration has changed */ +}; + +struct atmarp_ctrl { @@ -6769,7 +6818,7 @@ + +#endif --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/include/linux/atmclip.h Wed Nov 19 00:36:59 1997 ++++ work/include/linux/atmclip.h Thu Jan 15 22:49:10 1998 @@ -0,0 +1,21 @@ +/* atmclip.h - Classical IP over ATM */ + @@ -6793,11 +6842,11 @@ + +#endif --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/include/linux/atmdev.h Wed Nov 19 00:41:22 1997 -@@ -0,0 +1,289 @@ ++++ work/include/linux/atmdev.h Fri Mar 13 19:58:59 1998 +@@ -0,0 +1,304 @@ +/* atmdev.h - ATM device driver declarations */ + -+/* Written 1995-1997 by Werner Almesberger, EPFL LRC */ ++/* Written 1995-1998 by Werner Almesberger, EPFL LRC/ICA */ + + +#ifndef LINUX_ATMDEV_H @@ -6912,6 +6961,10 @@ +#include /* struct sk_buff */ +#include + ++#ifdef CONFIG_PROC_FS ++#include ++#endif ++ +#ifdef CONFIG_AREQUIPA +#include /* for struct sock */ +#endif @@ -6940,9 +6993,14 @@ +#define ATM_VF_SCTX ATM_SC_TX /* 2048; allow single-copy in the TX dir. */ +#define ATM_VF_SESSION 4096 /* VCC is p2mp session control descriptor */ +#define ATM_VF_HASSAP 8192 /* SAP has been set */ ++#define ATM_VF_CLOSE 32768 /* asynchronous close - treat like VF_RELEASED*/ + +#define ATM_DF_CLOSE 1 /* close device when last VCC is closed */ + ++#define ATM_PHY_SIG_LOST 0 /* no carrier/light */ ++#define ATM_PHY_SIG_UNKNOWN 1 /* carrier/light status is unknown */ ++#define ATM_PHY_SIG_FOUND 2 /* carrier/light okay */ ++ + +struct atm_vcc { + unsigned short flags; /* VCC flags (ATM_VF_*) */ @@ -7010,11 +7068,16 @@ + struct atm_vcc *last; /* last VCC (or undefined) */ + void *dev_data; /* per-device data */ + void *phy_data; /* private PHY date */ -+ unsigned long flags; /* device flags, TBD */ ++ unsigned long flags; /* device flags (ATM_DF_*) */ + struct atm_dev_addr *local; /* local ATM addresses */ + unsigned char esi[ESI_LEN]; /* ESI ("MAC" addr) */ + struct atm_cirange ci_range; /* VPI/VCI range */ + struct atm_dev_stats stats; /* statistics */ ++ char signal; /* signal status (ATM_PHY_SIG_*) */ ++#ifdef CONFIG_PROC_FS ++ struct proc_dir_entry *proc_entry; /* proc entry */ ++ char *proc_name; /* proc entry name */ ++#endif + struct atm_dev *prev,*next; /* linkage */ +}; + @@ -7023,7 +7086,7 @@ + * ioctl, getsockopt, setsockopt, and sg_send are optional and can be set to + * NULL. */ + -+/* OF: send_Oam flags */ ++/* OF: send_Oam Flags */ + +#define ATM_OF_IMMED 1 /* Attempt immediate delivery */ +#define ATM_OF_INRATE 2 /* Attempt in-rate delivery */ @@ -7053,6 +7116,7 @@ + int (*change_qos)(struct atm_vcc *vcc,struct atm_qos *qos,int flags); + void (*free_rx_skb)(struct atm_vcc *vcc, struct sk_buff *skb); + /* @@@ temporary hack */ ++ int (*proc_read)(struct atm_dev *dev,loff_t *pos,char *page); +}; + + @@ -7085,7 +7149,7 @@ + +#endif --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/include/linux/atmioc.h Wed Nov 19 00:36:59 1997 ++++ work/include/linux/atmioc.h Thu Jan 15 22:49:10 1998 @@ -0,0 +1,38 @@ +/* atmioc.h - ranges for ATM-related ioctl numbers */ + @@ -7126,11 +7190,79 @@ + +#endif --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/include/linux/atmsap.h Wed Nov 19 00:36:59 1997 -@@ -0,0 +1,163 @@ ++++ work/include/linux/atmlec.h Fri Mar 6 12:20:36 1998 +@@ -0,0 +1,65 @@ ++/* ++ * ++ * ATM Lan Emulation Daemon vs. driver interface ++ * ++ * carnil@cs.tut.fi ++ * ++ */ ++ ++#ifndef _ATMLEC_H_ ++#define _ATMLEC_H_ ++ ++#include ++#include ++#include ++/* ATM lec daemon control socket */ ++#define ATMLEC_CTRL _IO('a',ATMIOC_LANE) ++#define ATMLEC_DATA _IO('a',ATMIOC_LANE+1) ++#define ATMLEC_MCAST _IO('a',ATMIOC_LANE+2) ++ ++/* Maximum number of LEC interfaces (tweakable) */ ++#define MAX_LEC_ITF 4 ++ ++typedef enum { ++ l_set_mac_addr, l_del_mac_addr, ++ l_svc_setup, ++ l_addr_delete, l_topology_change, ++ l_flush_complete, l_arp_update, ++ l_config, l_flush_tran_id, ++ l_set_lecid, l_arp_xmt ++} atmlec_msg_type; ++ ++#define ATMLEC_MSG_TYPE_MAX l_arp_xmt ++ ++struct atmlec_config_msg { ++ unsigned int maximum_unknown_frame_count; ++ unsigned long max_unknown_frame_time; ++ unsigned short max_retry_count; ++ unsigned long aging_time; ++ unsigned long forward_delay_time; ++ unsigned long arp_response_time; ++ unsigned long flush_timeout; ++ unsigned long path_switching_delay; ++}; ++ ++struct atmlec_msg { ++ atmlec_msg_type type; ++ int sizeoftlvs; /* LANE2: if != 0, tlvs follow */ ++ union { ++ struct { ++ unsigned char mac_addr[ETH_ALEN]; ++ unsigned char atm_addr[ATM_ESA_LEN]; ++ unsigned long flag;/* Topology_change flag, ++ remoteflag, permanent flag, ++ lecid, transaction id */ ++ } normal; ++ struct atmlec_config_msg config; ++ } content; ++}; ++ ++struct atmlec_ioc { ++ int dev_num; ++ unsigned char atm_addr[ATM_ESA_LEN]; ++ unsigned char receive; /* 1= receive vcc, 0 = send_vcc */ ++}; ++#endif /* _ATMLEC_H_ */ +--- /dev/null Tue Jan 1 05:00:00 1980 ++++ work/include/linux/atmsap.h Thu Mar 5 16:37:51 1998 +@@ -0,0 +1,161 @@ +/* atmsap.h - ATM Service Access Point addressing definitions */ + -+/* Written 1995-1997 by Werner Almesberger, EPFL LRC */ ++/* Written 1995-1998 by Werner Almesberger, EPFL LRC/ICA */ + + +#ifndef _LINUX_ATMSAP_H @@ -7190,9 +7322,7 @@ +#define ATM_HL_NONE 0 /* HL not specified */ +#define ATM_HL_ISO 0x01 /* ISO */ +#define ATM_HL_USER 0x02 /* user-specific */ -+#if defined(UNI30) || defined(ALLOW_UNI30) +#define ATM_HL_HLP 0x03 /* high layer profile - UNI 3.0 only */ -+#endif +#define ATM_HL_VENDOR 0x04 /* vendor-specific application identifier */ +/* END_HL */ + @@ -7292,7 +7422,7 @@ + +#endif --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/include/linux/atmsvc.h Wed Nov 19 00:36:59 1997 ++++ work/include/linux/atmsvc.h Fri Mar 6 12:20:35 1998 @@ -0,0 +1,52 @@ +/* atmsvc.h - ATM signaling kernel-demon interface definitions */ + @@ -7346,8 +7476,8 @@ + (tp).max_pcr : (tp).min_pcr ? (tp).min_pcr : ATM_MAX_PCR) + +#endif ---- ref/include/linux/if_arp.h Sat Nov 15 03:41:25 1997 -+++ work/include/linux/if_arp.h Wed Nov 19 00:40:00 1997 +--- ref/include/linux/if_arp.h Tue Jan 13 01:44:26 1998 ++++ work/include/linux/if_arp.h Thu Jan 15 23:34:05 1998 @@ -35,6 +35,7 @@ #define ARPHRD_ARCNET 7 /* ARCnet */ #define ARPHRD_APPLETLK 8 /* APPLEtalk */ @@ -7356,7 +7486,7 @@ #define ARPHRD_METRICOM 23 /* Metricom STRIP (new IANA id) */ /* Dummy types for non ARP hardware */ -@@ -66,6 +67,9 @@ +@@ -70,6 +71,9 @@ #define ARPOP_REPLY 2 /* ARP reply */ #define ARPOP_RREQUEST 3 /* RARP request */ #define ARPOP_RREPLY 4 /* RARP reply */ @@ -7366,52 +7496,9 @@ /* ARP ioctl request. */ ---- ref/include/linux/proc_fs.h Sat Nov 15 03:40:51 1997 -+++ work/include/linux/proc_fs.h Wed Nov 19 00:38:55 1997 -@@ -36,6 +36,7 @@ - PROC_KSYMS, - PROC_DMA, - PROC_IOPORTS, -+ PROC_ATM, - #ifdef __SMP_PROF__ - PROC_SMP_PROF, - #endif -@@ -213,6 +214,16 @@ - #define PROC_OPENPROMD_FIRST (PROC_OPENPROM_FIRST+PROC_NOPENPROM) - #define PROC_NOPENPROMD 4096 - -+enum atm_directory_inos { -+ PROC_ATM_DEVICES = 384, -+ PROC_ATM_ARP, -+ PROC_ATM_LEC, -+ PROC_ATM_SVC, -+ PROC_ATM_PVC, -+ PROC_ATM_AREQUIPA, -+ PROC_ATM_LAST -+}; -+ - #define PROC_SUPER_MAGIC 0x9fa0 - - /* -@@ -258,6 +269,7 @@ - extern struct proc_dir_entry proc_root; - extern struct proc_dir_entry *proc_net; - extern struct proc_dir_entry *proc_scsi; -+extern struct proc_dir_entry proc_atm; - extern struct proc_dir_entry proc_sys; - extern struct proc_dir_entry proc_openprom; - extern struct proc_dir_entry proc_pid; -@@ -367,6 +379,7 @@ - extern struct inode_operations proc_kmsg_inode_operations; - extern struct inode_operations proc_link_inode_operations; - extern struct inode_operations proc_fd_inode_operations; -+extern struct inode_operations proc_atm_inode_operations; - #if CONFIG_AP1000 - extern struct inode_operations proc_ringbuf_inode_operations; - #endif ---- ref/include/linux/skbuff.h Sat Nov 15 03:40:52 1997 -+++ work/include/linux/skbuff.h Wed Nov 19 00:38:55 1997 -@@ -121,6 +121,24 @@ +--- ref/include/linux/skbuff.h Tue Jan 13 01:43:19 1998 ++++ work/include/linux/skbuff.h Thu Jan 15 23:32:59 1998 +@@ -115,6 +115,24 @@ __u32 shapestamp; /* Stamp for shaper */ __u16 shapepend; /* Pending */ #endif @@ -7437,7 +7524,7 @@ /* These are just the default values. This is run time configurable. --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/include/linux/sonet.h Wed Nov 19 00:36:59 1997 ++++ work/include/linux/sonet.h Thu Jan 15 22:49:10 1998 @@ -0,0 +1,52 @@ +/* sonet.h - SONET/SHD physical layer control */ + @@ -7491,22 +7578,20 @@ +#define SONET_FRSENSE_SIZE 6 /* C1[3],H1[3] (0xff for unknown) */ + +#endif ---- ref/include/net/arp.h Sat Nov 15 03:42:28 1997 -+++ work/include/net/arp.h Wed Nov 19 00:43:16 1997 -@@ -45,4 +45,7 @@ - extern int arp_bind_cache(struct hh_cache ** hhp, struct device *dev, unsigned short type, __u32 daddr); - extern int arp_update_cache(struct hh_cache * hh); - extern struct neighbour *arp_find_neighbour(struct dst_entry *dst, int); -+extern struct neighbour *clip_find_neighbour(struct dst_entry *dst,int resolve); -+extern int clip_arp_ioctl(struct device *dev,unsigned int cmd,void *arg); +--- ref/include/net/arp.h Tue Jan 13 01:46:43 1998 ++++ work/include/net/arp.h Thu Feb 12 11:16:08 1998 +@@ -18,4 +18,5 @@ + extern int arp_bind_neighbour(struct dst_entry *dst); + extern int arp_mc_map(u32 addr, u8 *haddr, struct device *dev, int dir); + extern void arp_ifdown(struct device *dev); + #endif /* _ARP_H */ --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/include/net/atmclip.h Wed Nov 19 00:44:35 1997 -@@ -0,0 +1,64 @@ ++++ work/include/net/atmclip.h Fri Mar 13 20:00:02 1998 +@@ -0,0 +1,66 @@ +/* net/atm/atmarp.h - RFC1577 ATM ARP */ + -+/* Written 1995-1997 by Werner Almesberger, EPFL LRC */ ++/* Written 1995-1998 by Werner Almesberger, EPFL LRC/ICA */ + + +#ifndef _ATMCLIP_H @@ -7521,7 +7606,7 @@ + + +#define CLIP_VCC(vcc) ((struct clip_vcc *) ((vcc)->user_back)) -+#define NEIGH2ENTRY(neigh) ((struct atmarp_entry *) (neigh)) ++#define NEIGH2ENTRY(neigh) ((struct atmarp_entry *) (neigh)->primary_key) + + +struct clip_vcc { @@ -7538,11 +7623,11 @@ + + +struct atmarp_entry { -+ struct neighbour neigh; -+ u32 ip; /* IP address !!!REMOVE!!! */ ++ u32 ip; /* IP address */ + struct clip_vcc *vccs; /* active VCCs; NULL if resolution is + pending */ + unsigned long expires; /* entry expiration time */ ++ struct neighbour *neigh; /* neighbour back-pointer */ + struct atmarp_entry *next; /* ugly linked list ... */ +}; + @@ -7560,18 +7645,20 @@ + + +extern struct atm_vcc *atmarpd; /* ugly */ -+ ++extern struct neigh_table clip_tbl; + +int clip_create(int number); +int clip_mkip(struct atm_vcc *vcc,int timeout); +int clip_setentry(struct atm_vcc *vcc,u32 ip); +int clip_encap(struct atm_vcc *vcc,int mode); + ++int clip_arp_ioctl(struct device *dev,unsigned int cmd,void *arg); ++ +#endif ---- ref/net/Config.in Thu Nov 13 21:58:50 1997 -+++ work/net/Config.in Wed Nov 19 00:36:59 1997 -@@ -21,6 +21,20 @@ - tristate 'The IPv6 protocol (EXPERIMENTAL)' CONFIG_IPV6 +--- ref/net/Config.in Tue Jan 13 00:28:48 1998 ++++ work/net/Config.in Sat Mar 7 00:16:04 1998 +@@ -22,6 +22,20 @@ + fi fi fi +if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then @@ -7583,26 +7670,27 @@ +# fi + if [ "$CONFIG_INET" = "y" ]; then + bool ' Classical IP over ATM' CONFIG_ATM_CLIP y -+ bool ' Application REQUested IP over ATM' CONFIG_AREQUIPA y ++# bool ' Application REQUested IP over ATM' CONFIG_AREQUIPA y + fi -+# bool ' LANE support' CONFIG_ATM_LANE y ++ tristate ' LAN Emulation (LANE) support' CONFIG_ATM_LANE y + fi +fi comment ' ' tristate 'The IPX protocol' CONFIG_IPX ---- ref/net/Makefile Thu Jul 17 04:22:51 1997 -+++ work/net/Makefile Wed Nov 19 00:36:59 1997 -@@ -9,7 +9,7 @@ +--- ref/net/Makefile Sun Nov 30 23:00:39 1997 ++++ work/net/Makefile Mon Feb 16 17:57:36 1998 +@@ -9,7 +9,8 @@ MOD_SUB_DIRS := ipv4 ALL_SUB_DIRS := 802 ax25 bridge core ethernet ipv4 ipv6 ipx unix appletalk \ -- netrom rose lapb x25 wanrouter sunrpc #decnet -+ netrom rose lapb x25 wanrouter sunrpc atm #decnet - SUB_DIRS := core ethernet unix +- netrom rose lapb x25 wanrouter netlink sched packet sunrpc #decnet ++ netrom rose lapb x25 wanrouter netlink sched packet sunrpc \ ++ atm #decnet + SUB_DIRS := core ethernet sched MOD_LIST_NAME := NET_MISC_MODULES -@@ -103,6 +103,10 @@ +@@ -130,6 +131,13 @@ ifeq ($(CONFIG_SUNRPC),m) MOD_SUB_DIRS += sunrpc endif @@ -7610,12 +7698,15 @@ + +ifeq ($(CONFIG_ATM),y) +SUB_DIRS += atm ++ifeq ($(CONFIG_ATM_LANE),m) ++ MOD_SUB_DIRS += atm ++endif endif ifeq ($(CONFIG_DECNET),y) ---- ref/net/protocols.c Tue Jun 17 01:36:02 1997 -+++ work/net/protocols.c Wed Nov 19 00:36:59 1997 -@@ -69,6 +69,10 @@ +--- ref/net/protocols.c Sun Nov 30 23:00:40 1997 ++++ work/net/protocols.c Thu Jan 15 22:49:10 1998 +@@ -79,6 +79,10 @@ extern void rif_init(struct net_proto *); #endif @@ -7626,7 +7717,7 @@ #ifdef NEED_LLC #define NEED_802 #include -@@ -97,6 +101,11 @@ +@@ -115,6 +119,11 @@ #ifdef CONFIG_TR { "RIF", rif_init }, /* RIF for Token ring */ #endif @@ -7638,12 +7729,36 @@ #ifdef NEED_LLC { "802.2LLC", llc_init }, /* 802.2 LLC */ ---- ref/net/ipv4/arp.c Thu Sep 18 00:43:20 1997 -+++ work/net/ipv4/arp.c Wed Nov 19 00:36:59 1997 -@@ -1827,6 +1827,21 @@ - return -EINVAL; - } +--- ref/net/ipv4/arp.c Tue Jan 13 00:28:25 1998 ++++ work/net/ipv4/arp.c Tue Jan 27 18:06:25 1998 +@@ -114,6 +114,9 @@ + #include + #endif + #endif ++#ifdef CONFIG_ATM_CLIP ++#include ++#endif + + #include + #include +@@ -400,7 +403,11 @@ + if (dev == NULL) + return 0; + if (dst->neighbour == NULL) +- dst->neighbour = __neigh_lookup(&arp_tbl, &((struct rtable*)dst)->rt_gateway, dev, 1); ++ dst->neighbour = __neigh_lookup( ++#ifdef CONFIG_ATM_CLIP ++ dev->type == ARPHRD_ATM ? &clip_tbl : ++#endif ++ &arp_tbl, &((struct rtable*)dst)->rt_gateway, dev, 1); + return (dst->neighbour != NULL); + } +@@ -857,6 +864,24 @@ + if ((r.arp_flags & ATF_COM) && r.arp_ha.sa_family != dev->type) + goto out; + } ++ +#ifdef CONFIG_ATM_CLIP + if (!dev) { + struct rtable *rt; @@ -7654,31 +7769,19 @@ + if (err) return err; + dev = rt->u.dst.dev; + ip_rt_put(rt); -+ } -+ -+ if (dev->type == ARPHRD_ATM) return clip_arp_ioctl(dev, cmd, arg); -+#endif ++ } + - switch(cmd) - { - case SIOCDARP: ---- ref/net/ipv4/route.c Thu Jun 26 21:33:41 1997 -+++ work/net/ipv4/route.c Wed Nov 19 00:36:59 1997 -@@ -368,6 +368,11 @@ - if (rt->u.dst.dev && rt->u.dst.dev->hard_header_cache) { - neigh = rt->u.dst.neighbour; - if (!neigh) -+#ifdef CONFIG_ATM_CLIP -+ if (rt->u.dst.dev->type == ARPHRD_ATM) -+ neigh = clip_find_neighbour(&rt->u.dst, 1); -+ else ++ if (dev->type == ARPHRD_ATM) { ++ err = clip_arp_ioctl(dev, cmd, arg); ++ goto out; ++ } +#endif - neigh = arp_find_neighbour(&rt->u.dst, 1); - if (neigh) { + switch(cmd) { + case SIOCDARP: --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/net/atm/Makefile Wed Nov 19 00:36:59 1997 -@@ -0,0 +1,48 @@ ++++ work/net/atm/Makefile Fri Mar 6 13:25:11 1998 +@@ -0,0 +1,52 @@ +# +# Makefile for the ATM Protocol Families. +# @@ -7696,8 +7799,8 @@ + +ifeq ($(CONFIG_ATM),y) + -+O_OBJS = addr.o common.o pvc.o raw.o signaling.o svc.o # party.o -+OX_OBJS = misc.o resources.o ++O_OBJS = addr.o pvc.o raw.o signaling.o svc.o # party.o ++OX_OBJS = common.o misc.o resources.o + +ifeq ($(CONFIG_MMU_HACKS),y) +O_OBJS += mmuio.o @@ -7720,7 +7823,11 @@ +endif + +ifeq ($(CONFIG_ATM_LANE),y) -+O_OBJS += lec.o lec_arpc.o ++O_OBJS += lec.o ++else ++ ifeq ($(CONFIG_ATM_LANE),m) ++ M_OBJS += lec.o ++ endif +endif + +endif @@ -7728,11 +7835,11 @@ + +include $(TOPDIR)/Rules.make --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/net/atm/addr.c Wed Nov 19 00:36:59 1997 -@@ -0,0 +1,157 @@ ++++ work/net/atm/addr.c Thu Feb 12 18:07:56 1998 +@@ -0,0 +1,159 @@ +/* net/atm/addr.c - Local ATM address registry */ + -+/* Written 1995-1997 by Werner Almesberger, EPFL LRC */ ++/* Written 1995-1998 by Werner Almesberger, EPFL LRC/ICA */ + + +#include @@ -7869,7 +7976,7 @@ +int get_addr(struct atm_dev *dev,struct sockaddr_atmsvc *u_buf,int size) +{ + struct atm_dev_addr *walk; -+ int total,error; ++ int total; + + lock_local(); + total = 0; @@ -7879,16 +7986,18 @@ + unlock_local(); + return -E2BIG; + } -+ error = copy_to_user(u_buf,&walk->addr, -+ sizeof(struct sockaddr_atmsvc)); -+ if (error) return error; ++ if (copy_to_user(u_buf,&walk->addr, ++ sizeof(struct sockaddr_atmsvc))) { ++ unlock_local(); ++ return -EFAULT; ++ } + u_buf++; + } + unlock_local(); + return total; +} --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/net/atm/addr.h Wed Nov 19 00:44:34 1997 ++++ work/net/atm/addr.h Fri Mar 13 20:00:07 1998 @@ -0,0 +1,18 @@ +/* net/atm/addr.h - Local ATM address registry */ + @@ -7909,11 +8018,11 @@ + +#endif --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/net/atm/clip.c Wed Nov 19 04:47:30 1997 -@@ -0,0 +1,667 @@ ++++ work/net/atm/clip.c Fri Mar 13 23:29:45 1998 +@@ -0,0 +1,728 @@ +/* clip.c - RFC1577 Classical IP over ATM */ + -+/* Written 1995-1997 by Werner Almesberger, EPFL LRC */ ++/* Written 1995-1998 by Werner Almesberger, EPFL LRC/ICA */ + + +#include @@ -7933,7 +8042,9 @@ +/* #include / * for net/route.h WAS IN 2155-VGER */ +#include /* for struct sockaddr_in */ +#include /* for IFF_UP */ ++#include +#include /* for struct rtable and routing */ ++#include /* ip_acct_output, etc. */ +#include /* for HZ */ +#include /* for htons etc. */ +#include /* save/restore_flags */ @@ -8023,33 +8134,42 @@ + +static void link_vcc(struct clip_vcc *clip_vcc,struct atmarp_entry *entry) +{ ++ DPRINTK("link_vcc %p to entry %p (neigh %p)\n",clip_vcc,entry, ++ entry->neigh); + clip_vcc->entry = entry; + clip_vcc->next = entry->vccs; + entry->vccs = clip_vcc; -+ clip_vcc->entry->neigh.lastused = jiffies; ++ entry->neigh->used = jiffies; +} + + +static void unlink_clip_vcc(struct clip_vcc *clip_vcc) +{ ++ struct atmarp_entry *entry = clip_vcc->entry; + struct clip_vcc **walk; + -+ if (!clip_vcc->entry) { ++ if (!entry) { + printk(KERN_CRIT "!clip_vcc->entry (clip_vcc %p)\n",clip_vcc); + return; + } -+ clip_vcc->entry->neigh.lastused = jiffies; -+ for (walk = &clip_vcc->entry->vccs; *walk; walk = &(*walk)->next) ++ entry->neigh->used = jiffies; ++ for (walk = &entry->vccs; *walk; walk = &(*walk)->next) + if (*walk == clip_vcc) { ++ int error; ++ + *walk = clip_vcc->next; /* atomic */ -+ if (!clip_vcc->entry->vccs) -+ clip_vcc->entry->expires = jiffies-1; -+ /* force resolution or expiration */ + clip_vcc->entry = NULL; ++ if (entry->vccs) return; ++ entry->expires = jiffies-1; ++ /* force resolution or expiration */ ++ error = neigh_update(entry->neigh,NULL,NUD_STALE,0,0); ++ if (error) ++ printk(KERN_CRIT "unlink_clip_vcc: " ++ "neigh_update failed with %d\n",error); + return; + } + printk(KERN_CRIT "ATMARP: unlink_clip_vcc failed (entry %p, vcc " -+ "0x%p)\n",clip_vcc->entry,clip_vcc); ++ "0x%p)\n",entry,clip_vcc); +} + + @@ -8069,30 +8189,37 @@ + struct neighbour *neigh; + + for (clip_vcc = (*entry)->vccs; clip_vcc; -+ clip_vcc = clip_vcc->next) ++ clip_vcc = clip_vcc->next) { ++ if (clip_vcc->vcc->family == PF_ATMPVC) ++ continue; + if (clip_vcc->last_use+clip_vcc->idle_timeout < + jiffies) { + DPRINTK("releasing vcc %p->%p of " + "entry %p\n",clip_vcc,clip_vcc->vcc, + *entry); -+ atm_async_release_vcc(clip_vcc->vcc); ++ atm_async_release_vcc(clip_vcc->vcc, ++ -ETIMEDOUT); + } ++ } + if ((*entry)->vccs || (*entry)->expires > jiffies) { + entry = &(*entry)->next; + continue; + } -+ if (atomic_read(&(*entry)->neigh.refcnt)) { ++ if (atomic_read(&(*entry)->neigh->refcnt)) { + struct sk_buff *skb; + ++ DPRINTK("destruction postponed with ref %d\n", ++ atomic_read(&(*entry)->neigh->refcnt)); + while ((skb = skb_dequeue( -+ &(*entry)->neigh.arp_queue)) != NULL) ++ &(*entry)->neigh->arp_queue)) != NULL) + dev_kfree_skb(skb,FREE_WRITE); + entry = &(*entry)->next; + continue; + } -+ neigh = &(*entry)->neigh; ++ neigh = (*entry)->neigh; + *entry = (*entry)->next; + DPRINTK("expired itf %p, neigh %p\n",itf,neigh); ++ neigh->tbl = NULL; + neigh_destroy(neigh); + } + } @@ -8103,17 +8230,6 @@ +} + + -+static struct atmarp_entry *clip_lookup(struct device *dev,u32 ip) -+{ -+ struct atmarp_entry *walk; -+ -+ DPRINTK("clip_lookup\n"); -+ for (walk = PRIV(dev)->table; walk; walk = walk->next) -+ if (walk->ip == ip) break; -+ return walk; -+} -+ -+ +static int clip_arp_rcv(struct sk_buff *skb) +{ + DPRINTK("clip_arp_rcv\n"); @@ -8141,8 +8257,7 @@ + return; + } + atm_return(vcc,skb->truesize); -+ clip_vcc->last_use = jiffies; -+ skb->dev = clip_vcc->entry ? clip_vcc->entry->neigh.dev : clip_devs; ++ skb->dev = clip_vcc->entry ? clip_vcc->entry->neigh->dev : clip_devs; + /* clip_vcc_entry == NULL if we don't have an IP address yet */ + if (!skb->dev) { + kfree_skb(skb,FREE_READ); @@ -8161,6 +8276,7 @@ + return; + } + } ++ clip_vcc->last_use = jiffies; + PRIV(skb->dev)->stats.rx_packets++; + netif_rx(skb); +} @@ -8168,18 +8284,90 @@ + +static void clip_neigh_destroy(struct neighbour *neigh) +{ -+ DPRINTK("clip_neigh_destroy\n"); ++ DPRINTK("clip_neigh_destroy (neigh %p)\n",neigh); + if (NEIGH2ENTRY(neigh)->vccs) + printk(KERN_CRIT "clip_neigh_destroy: vccs != NULL !!!\n"); + NEIGH2ENTRY(neigh)->vccs = (void *) 0xdeadbeef; +} + + ++static void clip_neigh_solicit(struct neighbour *neigh,struct sk_buff *skb) ++{ ++ DPRINTK("clip_neigh_solicit (neigh %p, skb %p)\n",neigh,skb); ++ to_atmarpd(act_need,PRIV(neigh->dev)->number, ++ *(u32 *) neigh->primary_key,NULL,0); ++} ++ ++ ++static void clip_neigh_error(struct neighbour *neigh,struct sk_buff *skb) ++{ ++ icmp_send(skb,ICMP_DEST_UNREACH,ICMP_HOST_UNREACH,0); ++ kfree_skb(skb,FREE_WRITE); ++} ++ ++ +static struct neigh_ops clip_neigh_ops = { + AF_INET, /* family */ -+ NULL, /* hash */ -+ NULL, /* resolve - @@@ THIS FIELD IS USELESS !!! */ -+ clip_neigh_destroy /* destructor */ ++ clip_neigh_destroy, /* destructor */ ++ clip_neigh_solicit, /* solicit */ ++ clip_neigh_error, /* error_report */ ++ neigh_resolve_output, /* output */ ++ neigh_connected_output, /* connected_output */ ++ ip_acct_output, /* hh_output */ ++ ip_acct_output /* queue_xmit */ ++}; ++ ++ ++static int clip_constructor(struct neighbour *neigh) ++{ ++ struct atmarp_entry *entry = (struct atmarp_entry *) neigh->primary_key; ++ struct device *dev = neigh->dev; ++ struct in_device *in_dev = dev->ip_ptr; ++ ++ DPRINTK("clip_constructor (neigh %p, entry %p)\n",neigh,entry); ++ if (!in_dev) return -EINVAL; ++ neigh->type = inet_addr_type(entry->ip); ++ if (neigh->type != RTN_UNICAST) return -EINVAL; ++ if (in_dev->arp_parms) neigh->parms = in_dev->arp_parms; ++ neigh->ops = &clip_neigh_ops; ++ neigh->output = neigh->nud_state & NUD_VALID ? ++ neigh->ops->connected_output : neigh->ops->output; ++ entry->neigh = neigh; ++ entry->vccs = NULL; ++ entry->expires = jiffies+ATMARP_RETRY_DELAY*HZ; ++ entry->next = PRIV(dev)->table; ++ PRIV(dev)->table = entry; ++ return 0; ++} ++ ++ ++struct neigh_table clip_tbl = { ++ NULL, /* next */ ++ AF_INET, /* family */ ++ sizeof(struct neighbour)+sizeof(struct atmarp_entry), /* entry_size */ ++ 4, /* key_len */ ++ clip_constructor, /* constructor */ ++ NULL, /* pconstructor */ ++ NULL, /* pdestructor */ ++ NULL, /* proxy_redo */ ++ { ++ NULL, ++ NULL, ++ 30*HZ, ++ 1*HZ, ++ 60*HZ, ++ 30*HZ, ++ 5*HZ, ++ 3, ++ 3, ++ 0, ++ 3, ++ 1*HZ, ++ (8*HZ)/10, ++ 1*HZ, ++ 64 ++ }, ++ 30*HZ,128,512,1024 /* copied from ARP ... */ +}; + + @@ -8193,37 +8381,6 @@ + */ + + -+struct neighbour *clip_find_neighbour(struct dst_entry *dst,int resolve) -+{ -+ struct rtable *rt = (struct rtable *) dst; -+ struct device *dev = dst->dev; -+ u32 ip = rt->rt_gateway; -+ struct atmarp_entry *entry; -+ -+ DPRINTK("clip_find_neighbour (ip %08x, resolve %d)\n",ip,resolve); -+ entry = clip_lookup(dev,ip); -+ if (entry) { -+ if (resolve != -1) atomic_inc(&entry->neigh.refcnt); -+ entry->neigh.lastused = jiffies; -+ return (struct neighbour *) entry; -+ } -+ if (!resolve) return NULL; -+ if (resolve > 0) to_atmarpd(act_need,PRIV(dev)->number,ip,NULL,0); -+ entry = (struct atmarp_entry *) neigh_alloc(sizeof(struct atmarp_entry), -+ &clip_neigh_ops); -+ if (!entry) return NULL; -+ atomic_set(&entry->neigh.refcnt,resolve < 0 ? 0 : 1); -+ entry->neigh.dev = dev; -+ entry->neigh.lastused = jiffies; -+ entry->ip = ip; -+ entry->vccs = NULL; -+ entry->expires = jiffies+ATMARP_RETRY_DELAY*HZ; -+ entry->next = PRIV(dev)->table; -+ PRIV(dev)->table = entry; -+ return (struct neighbour *) entry; -+} -+ -+ +int clip_encap(struct atm_vcc *vcc,int mode) +{ + CLIP_VCC(vcc)->encap = mode; @@ -8236,7 +8393,7 @@ +{ + void *here; + -+ DPRINTK("clip_hard_header\n"); ++ DPRINTK("clip_hard_header (skb %p)\n",skb); + here = skb_push(skb,RFC1483LLC_LEN); + memcpy(here,llc_oui,sizeof(llc_oui)); + ((u16 *) here)[3] = htons(type); @@ -8256,32 +8413,37 @@ +{ + struct atmarp_entry *entry; + -+ DPRINTK("clip_start_xmit\n"); ++ DPRINTK("clip_start_xmit (skb %p)\n",skb); + if (!skb->dst) { + printk(KERN_ERR "clip_start_xmit: skb->dst == NULL\n"); + dev_kfree_skb(skb,FREE_WRITE); + return 0; + } + if (!skb->dst->neighbour) { ++#if 0 + skb->dst->neighbour = clip_find_neighbour(skb->dst,1); + if (!skb->dst->neighbour) { + dev_kfree_skb(skb,FREE_WRITE); /* lost that one */ + PRIV(dev)->stats.tx_dropped++; + return 0; + } ++#endif ++printk("clip_start_xmit: NO NEIGHBOUR !\n"); ++return 0; + } -+ entry = (struct atmarp_entry *) skb->dst->neighbour; ++ entry = NEIGH2ENTRY(skb->dst->neighbour); + if (!entry->vccs) { + if (entry->expires < jiffies) /* should be resolved */ + to_atmarpd(act_need,PRIV(dev)->number,entry->ip,NULL,0); -+ if (entry->neigh.arp_queue.qlen < ATMARP_MAX_UNRES_PACKETS) -+ skb_queue_tail(&entry->neigh.arp_queue,skb); ++ if (entry->neigh->arp_queue.qlen < ATMARP_MAX_UNRES_PACKETS) ++ skb_queue_tail(&entry->neigh->arp_queue,skb); + else { + dev_kfree_skb(skb,FREE_WRITE); + PRIV(dev)->stats.tx_dropped++; + } + return 0; + } ++ DPRINTK("neigh %p, vccs %p\n",entry,entry->vccs); + skb->atm.vcc = entry->vccs->vcc; + DPRINTK("using neighbour %p, vcc %p\n",skb->dst->neighbour, + skb->atm.vcc); @@ -8316,6 +8478,7 @@ + if (!vcc->push) return -EBADFD; + clip_vcc = kmalloc(sizeof(struct clip_vcc),GFP_KERNEL); + if (!clip_vcc) return -ENOMEM; ++ DPRINTK("mkip clip_vcc %p vcc %p\n",clip_vcc,vcc); + clip_vcc->vcc = vcc; + vcc->user_back = clip_vcc; + clip_vcc->entry = NULL; @@ -8344,7 +8507,6 @@ +{ + struct neighbour *neigh; + struct atmarp_entry *entry; -+ /*unsigned long flags;*/ + int error; + struct clip_vcc *clip_vcc; + struct rtable *rt; @@ -8365,22 +8527,27 @@ + } + error = ip_route_output(&rt,ip,0,1,0); + if (error) return error; -+ neigh = clip_find_neighbour(&rt->u.dst,-1); -+ /* allocate but don't resolve */ ++ start_bh_atomic(); ++ if (!rt->u.dst.dev) printk(KERN_CRIT "!rt->u.dst.dev ?????\n"); ++ neigh = __neigh_lookup(&clip_tbl,&ip,rt->u.dst.dev,1); + ip_rt_put(rt); -+ if (!neigh) return -ENOMEM; ++ if (!neigh) { ++ end_bh_atomic(); ++ return -ENOMEM; ++ } + entry = NEIGH2ENTRY(neigh); -+ if (entry == clip_vcc->entry) return 0; -+ if (!clip_vcc->entry) DPRINTK("setentry: add\n"); -+ else { -+ DPRINTK("setentry: update\n"); -+ unlink_clip_vcc(clip_vcc); ++ if (entry != clip_vcc->entry) { ++ if (!clip_vcc->entry) DPRINTK("setentry: add\n"); ++ else { ++ DPRINTK("setentry: update\n"); ++ unlink_clip_vcc(clip_vcc); ++ } ++ link_vcc(clip_vcc,entry); + } -+ link_vcc(clip_vcc,entry); -+ if (skb_peek(&neigh->arp_queue)) -+ clip_start_xmit(skb_dequeue(&neigh->arp_queue), -+ entry->neigh.dev); -+ return 0; ++ error = neigh_update(neigh,llc_oui,NUD_PERMANENT,1,0); ++ neigh_release(neigh); ++ end_bh_atomic(); ++ return error; +} + + @@ -8388,11 +8555,9 @@ +{ + struct atmarpreq req; + __u32 *ip; -+ int error; + + DPRINTK("clip_ioctl\n"); -+ error = copy_from_user(&req,arg,sizeof(struct atmarpreq)); -+ if (error) return error; ++ if (copy_from_user(&req,arg,sizeof(struct atmarpreq))) return -EFAULT; + if (req.arp_pa.sa_family != AF_INET) return -EPFNOSUPPORT; + ip = &((struct sockaddr_in *) &req.arp_pa)->sin_addr.s_addr; +#if 0 /* ??? fix later @@@ */ @@ -8484,6 +8649,11 @@ + DPRINTK("clip_device_event NETDEV_DOWN\n"); + (void) to_atmarpd(act_down,PRIV(dev)->number,0,NULL,0); + break; ++ case NETDEV_CHANGE: ++ DPRINTK("clip_device_event NETDEV_CHANGE\n"); ++ (void) to_atmarpd(act_change,PRIV(dev)->number,0,NULL, ++ 0); ++ break; + case NETDEV_REBOOT: + case NETDEV_REGISTER: + DPRINTK("clip_device_event %ld\n",event); @@ -8579,14 +8749,15 @@ + return 0; +} --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/net/atm/common.c Wed Nov 19 03:40:12 1997 -@@ -0,0 +1,858 @@ ++++ work/net/atm/common.c Fri Mar 13 20:18:26 1998 +@@ -0,0 +1,919 @@ +/* net/atm/common.c - ATM sockets (common part for PVC and SVC) */ + -+/* Written 1995-1997 by Werner Almesberger, EPFL LRC */ ++/* Written 1995-1998 by Werner Almesberger, EPFL LRC/ICA */ + + +#include ++#include +#include /* struct socket, struct net_proto, struct + proto_ops */ +#include /* ATM stuff */ @@ -8614,7 +8785,7 @@ +#include +#endif + -+#ifdef CONFIG_ATM_LANE ++#if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE) +#include +#include "lec.h" +#include "lec_arpc.h" @@ -8639,6 +8810,40 @@ +#define DPRINTK(format,args...) printk(KERN_DEBUG format,##args) +#else +#define DPRINTK(format,args...) ++ ++#endif ++/* ++ * The attach functions are used in common.c::atm_ioctl(), ++ * ptr_to_get_dev_lec is used in proc.c::atm_info(). ++ * The functions are defined in lec.c. ++ * When lec module initializes itself it calls atm_lane_setup ++ * in lec.c::init_module(). ++ */ ++#ifdef CONFIG_ATM_LANE ++static int (*ptr_to_lecd_attach)(struct atm_vcc *vcc, int arg) = lecd_attach; ++static int (*ptr_to_lec_mcast_attach)(struct atm_vcc *vcc, int arg) = lec_mcast_attach; ++static int (*ptr_to_lec_vcc_attach)(struct atm_vcc *vcc, void *arg) = lec_vcc_attach; ++struct device **(*ptr_to_get_dev_lec)(void) = get_dev_lec; ++#endif ++ ++#ifdef CONFIG_ATM_LANE_MODULE ++static int (*ptr_to_lecd_attach)(struct atm_vcc *vcc, int arg) = NULL; ++static int (*ptr_to_lec_mcast_attach)(struct atm_vcc *vcc, int arg) = NULL; ++static int (*ptr_to_lec_vcc_attach)(struct atm_vcc *vcc, void *arg) = NULL; ++struct device **(*ptr_to_get_dev_lec)(void) = NULL; ++ ++void atm_lane_setup (int (*attach)(struct atm_vcc *vcc, int arg), ++ int (*mcast)(struct atm_vcc *vcc, int arg), ++ int (*vcc)(struct atm_vcc *vcc, void *arg), ++ struct device **(*dev_lec_ptr)(void)) { ++ ptr_to_lecd_attach = attach; ++ ptr_to_lec_mcast_attach = mcast; ++ ptr_to_lec_vcc_attach = vcc; ++ ptr_to_get_dev_lec = dev_lec_ptr; ++ ++} ++ ++EXPORT_SYMBOL(atm_lane_setup); +#endif + + @@ -8730,9 +8935,10 @@ +} + + -+void atm_async_release_vcc(struct atm_vcc *vcc) ++void atm_async_release_vcc(struct atm_vcc *vcc,int reply) +{ -+ vcc->flags |= ATM_VF_RELEASED; ++ vcc->flags |= ATM_VF_CLOSE; ++ vcc->reply = reply; + /*vcc->flags &= ~ATM_VF_READY;*/ + wake_up(&vcc->sleep); +} @@ -8893,7 +9099,7 @@ + save_flags(cpu_flags); + cli(); + while (!(skb = skb_dequeue(&vcc->recvq))) { -+ if (vcc->flags & ATM_VF_RELEASED) { ++ if (vcc->flags & (ATM_VF_RELEASED | ATM_VF_CLOSE)) { + restore_flags(cpu_flags); + return vcc->reply; + } @@ -8906,7 +9112,7 @@ + return -EAGAIN; + } + interruptible_sleep_on(&vcc->sleep); -+ if (current->signal & ~current->blocked) { ++ if (signal_pending(current)) { + restore_flags(cpu_flags); + return -ERESTARTSYS; + } @@ -8930,7 +9136,8 @@ + for (cnt = 0; (cnt < skb->atm.iovcnt) && el; cnt++) { +/*printk("s-g???: %p -> %p (%d)\n",iov->iov_base,p,iov->iov_len);*/ + error = copy_to_user(p,iov->iov_base, -+ (iov->iov_len > el) ? el : iov->iov_len); ++ (iov->iov_len > el) ? el : iov->iov_len) ? ++ -EFAULT : 0; + if (error) break; + p += iov->iov_len; + el -= (iov->iov_len > el)?el:iov->iov_len; @@ -8949,7 +9156,7 @@ + else +#endif + { -+ error = copy_to_user(buff,skb->data,eff_len); ++ error = copy_to_user(buff,skb->data,eff_len) ? -EFAULT : 0; + if (!vcc->dev->ops->free_rx_skb) kfree_skb(skb,FREE_READ); + else vcc->dev->ops->free_rx_skb(vcc, skb); + } @@ -8973,7 +9180,7 @@ + buff = m->msg_iov->iov_base; + size = m->msg_iov->iov_len; + vcc = ATM_SD(sock); -+ if (vcc->flags & ATM_VF_RELEASED) return vcc->reply; ++ if (vcc->flags & (ATM_VF_RELEASED | ATM_VF_CLOSE)) return vcc->reply; + if (!(vcc->flags & ATM_VF_READY)) return -EPIPE; + if (!size) return 0; + /* verify_area is done by net/socket.c */ @@ -8990,8 +9197,7 @@ + GFP_KERNEL))) { + if (m->msg_flags & MSG_DONTWAIT) return -EAGAIN; + interruptible_sleep_on(&vcc->wsleep); -+ if (current->signal & ~current->blocked) -+ return -ERESTARTSYS; ++ if (signal_pending(current)) return -ERESTARTSYS; + } + skb_put(skb,size); + res = lock_user((unsigned long) buff,size,max_iov, @@ -9015,16 +9221,15 @@ + while (!(skb = vcc->alloc_tx(vcc,eff))) { + if (m->msg_flags & MSG_DONTWAIT) return -EAGAIN; + interruptible_sleep_on(&vcc->wsleep); -+ if (current->signal & ~current->blocked) -+ return -ERESTARTSYS; -+ if (vcc->flags & ATM_VF_RELEASED) return vcc->reply; ++ if (signal_pending(current)) return -ERESTARTSYS; ++ if (vcc->flags & (ATM_VF_RELEASED | ATM_VF_CLOSE)) ++ return vcc->reply; + if (!(vcc->flags & ATM_VF_READY)) return -EPIPE; + } + skb->atm.iovcnt = 0; -+ error = copy_from_user(skb_put(skb,size),buff,size); -+ if (error) { ++ if (copy_from_user(skb_put(skb,size),buff,size)) { + kfree_skb(skb,FREE_WRITE); -+ return error; ++ return -EFAULT; + } + if (eff != size) memset(skb->data+size,0,eff-size); + error = vcc->dev->ops->send(vcc,skb); @@ -9043,7 +9248,7 @@ + mask = 0; + if (skb_peek(&vcc->recvq) || skb_peek(&vcc->listenq)) + mask |= POLLIN | POLLRDNORM; -+ if (vcc->flags & ATM_VF_RELEASED) mask |= POLLHUP; ++ if (vcc->flags & (ATM_VF_RELEASED | ATM_VF_CLOSE)) mask |= POLLHUP; + if (sock->state != SS_CONNECTING) { + if (vcc->qos.txtp.traffic_class != ATM_NONE && + vcc->qos.txtp.max_sdu+atomic_read(&vcc->tx_inuse)+ @@ -9069,10 +9274,10 @@ + if (arg) + error = copy_to_user(arg,&dev->stats, + sizeof(struct atm_dev_stats)); -+ if (zero) ++ if (zero && !error) + memset(&dev->stats,0,sizeof(struct atm_dev_stats)); + restore_flags(flags); -+ return error; ++ return error ? -EFAULT : 0; +} + + @@ -9096,34 +9301,53 @@ +{ + struct atm_dev *dev; + struct atm_vcc *vcc; ++ int *tmp_buf; + void *buf; + int error,len,size,number; + + vcc = ATM_SD(sock); + switch (cmd) { ++ case TIOCOUTQ: ++ if (sock->state != SS_CONNECTED || ++ !(vcc->flags & ATM_VF_READY)) return -EINVAL; ++ return put_user(vcc->tx_quota- ++ atomic_read(&vcc->tx_inuse)-ATM_PDU_OVHD, ++ (int *) arg) ? -EFAULT : 0; ++ case TIOCINQ: ++ { ++ struct sk_buff *skb; ++ ++ if (sock->state != SS_CONNECTED) ++ return -EINVAL; ++ skb = skb_peek(&vcc->recvq); ++ return put_user(skb ? skb->len : 0,(int *) arg) ++ ? -EFAULT : 0; ++ } + case ATM_GETNAMES: -+ error = get_user(buf, -+ &((struct atm_iobuf *) arg)->buffer); -+ if (error) return error; -+ error = get_user(len, -+ &((struct atm_iobuf *) arg)->length); -+ if (error) return error; ++ if (get_user(buf, ++ &((struct atm_iobuf *) arg)->buffer)) ++ return -EFAULT; ++ if (get_user(len, ++ &((struct atm_iobuf *) arg)->length)) ++ return -EFAULT; + size = 0; -+ for (dev = atm_devs; dev; dev = dev->next) { ++ for (dev = atm_devs; dev; dev = dev->next) + size += sizeof(int); -+ if (size > len) return -E2BIG; -+ error = put_user(dev->number,(int *) buf); -+ ((int *) buf)++; -+ /* @@@ race if page fault */ -+ } ++ if (size > len) return -E2BIG; ++ tmp_buf = kmalloc(size,GFP_KERNEL); ++ if (!tmp_buf) return -ENOMEM; ++ for (dev = atm_devs; dev; dev = dev->next) ++ *tmp_buf++ = dev->number; ++ if (copy_to_user(buf,(char *) tmp_buf-size,size)) ++ return -EFAULT; + return put_user(size, -+ &((struct atm_iobuf *) arg)->length); ++ &((struct atm_iobuf *) arg)->length) ? -EFAULT : 0; + case SIOCGSTAMP: /* borrowed from IP */ + if (!vcc->timestamp.tv_sec) return -ENOENT; + vcc->timestamp.tv_sec += vcc->timestamp.tv_usec/1000000; + vcc->timestamp.tv_usec %= 1000000; + return copy_to_user((void *) arg,&vcc->timestamp, -+ sizeof(struct timeval)); ++ sizeof(struct timeval)) ? -EFAULT : 0; + case ATM_SETSC: + if (arg & ~(ATM_VF_SCRX | ATM_VF_SCTX)) return -EINVAL; + /* @@@ race condition - should split flags into @@ -9191,18 +9415,22 @@ + arequipa_work(); + return 0; +#endif -+#ifdef CONFIG_ATM_LANE ++#if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE) + case ATMLEC_CTRL: + if (!suser()) return -EPERM; -+ error = lecd_attach(vcc, (int)arg); -+ if (error >=0) sock->state = SS_CONNECTED; ++ if (ptr_to_lecd_attach == NULL) { ++ printk ("no lec, try insmod lec first\n"); ++ return -ENOSYS; ++ } ++ error = ptr_to_lecd_attach(vcc, (int)arg); ++ if (error >= 0) sock->state = SS_CONNECTED; + return error; + case ATMLEC_MCAST: + if (!suser()) return -EPERM; -+ return lec_mcast_attach(vcc, (int)arg); ++ return ptr_to_lec_mcast_attach(vcc, (int)arg); + case ATMLEC_DATA: + if (!suser()) return -EPERM; -+ return lec_vcc_attach(vcc, (void*)arg); ++ return ptr_to_lec_vcc_attach(vcc, (void*)arg); +#endif +#ifdef CONFIG_ATM_TCP + case SIOCSIFATMTCP: @@ -9214,22 +9442,20 @@ + default: + break; + } -+ error = get_user(buf,&((struct atmif_sioc *) arg)->arg); -+ if (error) return error; -+ error = get_user(len,&((struct atmif_sioc *) arg)->length); -+ if (error) return error; -+ error = get_user(number,&((struct atmif_sioc *) arg)->number); -+ if (error) return error; ++ if (get_user(buf,&((struct atmif_sioc *) arg)->arg)) return -EFAULT; ++ if (get_user(len,&((struct atmif_sioc *) arg)->length)) return -EFAULT; ++ if (get_user(number,&((struct atmif_sioc *) arg)->number)) ++ return -EFAULT; + if (!(dev = atm_find_dev(number))) return -ENODEV; + size = 0; + switch (cmd) { + case ATM_GETTYPE: + size = strlen(dev->type)+1; -+ error = copy_to_user(buf,dev->type,size); ++ if (copy_to_user(buf,dev->type,size)) return -EFAULT; + break; + case ATM_GETESI: + size = ESI_LEN; -+ error = copy_to_user(buf,dev->esi,size); ++ if (copy_to_user(buf,dev->esi,size)) return -EFAULT; + break; + case ATM_SETESI: + { @@ -9244,8 +9470,8 @@ + unsigned char esi[ESI_LEN]; + + if (!suser()) return -EPERM; -+ error = copy_from_user(esi,buf,ESI_LEN); -+ if (error) return error; ++ if (copy_from_user(esi,buf,ESI_LEN)) ++ return -EFAULT; + memcpy(dev->esi,esi,ESI_LEN); + return ESI_LEN; + } @@ -9255,10 +9481,12 @@ + case ATM_GETSTAT: + size = sizeof(struct atm_dev_stats); + error = fetch_stats(dev,buf,cmd == ATM_GETSTATZ); ++ if (error) return error; + break; + case ATM_GETCIRANGE: + size = sizeof(sizeof(struct atm_cirange)); -+ error = copy_to_user(buf,&dev->ci_range,size); ++ if (copy_to_user(buf,&dev->ci_range,size)) ++ return -EFAULT; + break; + case ATM_RSTADDR: + if (!suser()) return -EPERM; @@ -9270,8 +9498,8 @@ + { + struct sockaddr_atmsvc addr; + -+ error = copy_from_user(&addr,buf,sizeof(addr)); -+ if (error) return error; ++ if (copy_from_user(&addr,buf,sizeof(addr))) ++ return -EFAULT; + if (cmd == ATM_ADDADDR) + return add_addr(dev,&addr); + else return del_addr(dev,&addr); @@ -9282,7 +9510,7 @@ + /* may return 0, but later on size == 0 means "don't + write the length" */ + return put_user(size, -+ &((struct atmif_sioc *) arg)->length); ++ &((struct atmif_sioc *) arg)->length) ? -EFAULT : 0; + case ATM_SETCIRANGE: + case SONET_GETSTATZ: + case SONET_SETDIAG: @@ -9295,8 +9523,9 @@ + size = dev->ops->ioctl(dev,cmd,buf); + if (size < 0) return size; + } -+ if (error || !size) return error; -+ return put_user(size,&((struct atmif_sioc *) arg)->length); ++ if (!size) return 0; ++ return put_user(size,&((struct atmif_sioc *) arg)->length) ? ++ -EFAULT : 0; +} + + @@ -9352,16 +9581,16 @@ + vcc = ATM_SD(sock); + switch (optname) { + case SO_SNDBUF: -+ error = get_user(value,(unsigned long *) optval); -+ if (error) return error; ++ if (get_user(value,(unsigned long *) optval)) ++ return -EFAULT; + if (!value) value = ATM_TXBQ_DEF; + if (value < ATM_TXBQ_MIN) value = ATM_TXBQ_MIN; + if (value > ATM_TXBQ_MAX) value = ATM_TXBQ_MAX; + vcc->tx_quota = value; + return 0; + case SO_RCVBUF: -+ error = get_user(value,(unsigned long *) optval); -+ if (error) return error; ++ if (get_user(value,(unsigned long *) optval)) ++ return -EFAULT; + if (!value) value = ATM_RXBQ_DEF; + if (value < ATM_RXBQ_MIN) value = ATM_RXBQ_MIN; + if (value > ATM_RXBQ_MAX) value = ATM_RXBQ_MAX; @@ -9371,8 +9600,8 @@ + { + struct atm_qos qos; + -+ error = copy_from_user(&qos,optval,sizeof(qos)); -+ if (error) return error; ++ if (copy_from_user(&qos,optval,sizeof(qos))) ++ return -EFAULT; + error = check_qos(&qos); + if (error) return error; + if (sock->state == SS_CONNECTED) @@ -9400,16 +9629,19 @@ + vcc = ATM_SD(sock); + switch (optname) { + case SO_SNDBUF: -+ return put_user(vcc->tx_quota,(unsigned long *) optval); ++ return put_user(vcc->tx_quota,(unsigned long *) optval) ++ ? -EFAULT : 0; + case SO_RCVBUF: -+ return put_user(vcc->rx_quota,(unsigned long *) optval); ++ return put_user(vcc->rx_quota,(unsigned long *) optval) ++ ? -EFAULT : 0; + case SO_BCTXOPT: + /* fall through */ + case SO_BCRXOPT: + break; + case SO_ATMQOS: + if (!(vcc->flags & ATM_VF_HASQOS)) return -EINVAL; -+ return copy_to_user(optval,&vcc->qos,sizeof(vcc->qos)); ++ return copy_to_user(optval,&vcc->qos,sizeof(vcc->qos)) ? ++ -EFAULT : 0; + default: + if (level == SOL_SOCKET) return -EINVAL; + break; @@ -9431,20 +9663,19 @@ +int atm_getsockopt(struct socket *sock,int level,int optname, + char *optval,int *optlen) +{ -+ int error,len; ++ int len; + -+ error = get_user(len,optlen); -+ if (error) return error; ++ if (get_user(len,optlen)) return -EFAULT; + if (level == __SO_LEVEL(optname) && len != __SO_SIZE(optname)) + return -EINVAL; + return atm_do_getsockopt(sock,level,optname,optval,len); +} --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/net/atm/common.h Wed Nov 19 00:36:59 1997 -@@ -0,0 +1,42 @@ ++++ work/net/atm/common.h Fri Mar 13 19:57:08 1998 +@@ -0,0 +1,44 @@ +/* net/atm/common.h - ATM sockets (common part for PVC and SVC) */ + -+/* Written 1995-1997 by Werner Almesberger, EPFL LRC */ ++/* Written 1995-1998 by Werner Almesberger, EPFL LRC/ICA */ + + +#ifndef NET_ATM_COMMON_H @@ -9471,9 +9702,11 @@ +int atm_connect_vcc(struct atm_vcc *vcc,int itf,short vpi,int vci); +int atm_release_vcc(struct atm_vcc *vcc,int free_vcc); +int atm_change_qos(struct atm_vcc *vcc,struct atm_qos *qos); -+void atm_async_release_vcc(struct atm_vcc *vcc); ++void atm_async_release_vcc(struct atm_vcc *vcc,int reply); +void atm_shutdown_dev(struct atm_dev *dev); + ++int atm_proc_init(void); ++ +/* SVC */ + +void svc_callback(struct atm_vcc *vcc); @@ -9485,7 +9718,7 @@ + +#endif --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/net/atm/ipcommon.c Wed Nov 19 00:36:59 1997 ++++ work/net/atm/ipcommon.c Thu Jan 15 22:49:11 1998 @@ -0,0 +1,52 @@ +/* net/atm/ipcommon.c - Common items for all ways of doing IP over ATM */ + @@ -9540,7 +9773,7 @@ + skb_queue_head_init(from); +} --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/net/atm/ipcommon.h Wed Nov 19 00:44:41 1997 ++++ work/net/atm/ipcommon.h Fri Mar 13 20:00:17 1998 @@ -0,0 +1,23 @@ +/* net/atm/ipcommon.h - Common items for all ways of doing IP over ATM */ + @@ -9566,7 +9799,7 @@ + +#endif --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/net/atm/misc.c Wed Nov 19 00:36:59 1997 ++++ work/net/atm/misc.c Fri Mar 6 21:29:38 1998 @@ -0,0 +1,187 @@ +/* net/atm/misc.c - Various functions for use by ATM drivers */ + @@ -9756,85 +9989,2279 @@ + +#endif --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/net/atm/proc.c Wed Nov 19 00:36:59 1997 -@@ -0,0 +1,538 @@ -+/* net/atm/proc.c - ATM /proc interface */ -+ -+/* Written 1995-1997 by Werner Almesberger, EPFL LRC */ ++++ work/net/atm/lec.c Fri Mar 13 23:09:42 1998 +@@ -0,0 +1,1895 @@ ++/* ++ * lec.c: Lan Emulation driver ++ * Marko Kiiskila carnil@cs.tut.fi ++ * ++ */ + ++#include + -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include ++/* We are ethernet device */ ++#include +#include -+#include -+#include -+#include ++#include ++#include ++#include ++#include ++#include +#include -+#include /* for HZ */ -+#include "resources.h" -+#include "signaling.h" /* to get sigd - ugly too */ ++#include ++#include ++#include + -+#ifdef CONFIG_AREQUIPA -+#include -+void atm_push_arequipa(struct atm_vcc *vcc,struct sk_buff *skb); -+#endif ++/* And atm device */ ++#include ++#include + -+#ifdef CONFIG_ATM_CLIP -+#include ++/* Modular too */ ++#include ++#include ++ ++#include "lec.h" ++#include "lec_arpc.h" ++#include "tunable.h" ++ ++ ++#define DPRINTK(format,args...) ++/* ++#define DPRINTK printk ++*/ ++#define DUMP_PACKETS 0 /* 0 = None, ++ * 1 = 30 first bytes ++ * 2 = Whole packet ++ */ ++ ++static int lec_open(struct device *dev); ++static int lec_send_packet(struct sk_buff *skb, struct device *dev); ++static int lec_close(struct device *dev); ++static struct enet_statistics *lec_get_stats(struct device *dev); ++static int lec_init(struct device *dev); ++static __inline__ struct lec_arp_table* lec_arp_find(struct lec_priv *priv, ++ unsigned char *mac_addr); ++/* LANE2 functions */ ++void lane2_associate_ind (struct lec_priv *priv, u8 *mac_address, ++ u8 *tlvs, u32 sizeoftlvs); ++int lane2_resolve(u8 *dst_mac, int force, struct device *dev, ++ u8 **tlvs, u32 *sizeoftlvs); ++ ++/* will be lec0, lec1, lec2 etc. */ ++static char myname[] = "lecx"; ++ ++/* Device structures */ ++static struct device *dev_lec[MAX_LEC_ITF]; ++ ++/* This will be called from proc.c via function pointer */ ++struct device **get_dev_lec (void) { ++ return &dev_lec[0]; ++} ++ ++/* ++ * Open/initialize the netdevice. This is called (in the current kernel) ++ * sometime after booting when the 'ifconfig' program is run. ++ * ++ * This routine should set everything up anew at each open, even ++ * registers that "should" only need to be set once at boot, so that ++ * there is non-reboot way to recover if something goes wrong. ++ */ ++ ++static int ++lec_open(struct device *dev) ++{ ++ struct lec_priv *priv = (struct lec_priv *)dev->priv; ++ ++ dev->tbusy = 0; ++ dev->start = 1; ++ dev->interrupt = 1; ++ memset(&priv->stats,0,sizeof(struct enet_statistics)); ++ ++ return 0; ++} ++void testi(struct sk_buff *skb, struct device *dev) ++{ ++ char dst_mac[] = {0,2,3,4,5,0}; ++ u8 *tlvs = kmalloc(6, GFP_KERNEL); ++ size_t sizeoftlvs = 6; ++ tlvs[0] = 1; ++ tlvs[1] = 2; ++ tlvs[2] = 3; ++ tlvs[3] = 4; ++ tlvs[4] = 1; ++ tlvs[5] = 42; ++ ++ lane2_resolve(dst_mac, 1, dev, &tlvs, &sizeoftlvs); ++ kfree(tlvs); ++} ++ ++static int ++lec_send_packet(struct sk_buff *skb, struct device *dev) ++{ ++ struct lec_priv *priv = (struct lec_priv *)dev->priv; ++ struct lecdatahdr_8023 *lec_h; ++ struct atm_vcc *send_vcc; ++ unsigned char *nb; ++#if DUMP_PACKETS > 0 ++ char buf[300]; ++ int i=0; ++#endif /* DUMP_PACKETS >0 */ ++ ++ /* testi(skb, dev); */ ++ DPRINTK("Lec_send_packet called\n"); ++ if (!priv->lecd) { ++ printk("%s:No lecd attached\n",dev->name); ++ priv->stats.tx_errors++; ++ return -EUNATCH; ++ } ++ if (dev->tbusy) { ++ /* ++ * If we get here, some higher level has decided we are broken. ++ * There should really be a "kick me" function call instead. ++ */ ++ priv->stats.tx_dropped++; ++ printk("%s: lec_send_packet: transmit timed out, dropping packet...\n", dev->name); ++ dev_kfree_skb(skb, FREE_WRITE); ++ dev->tbusy=0; ++ return 0; ++#if 0 ++ dev->tbusy = 1; ++ return 1; ++#endif ++ } ++ ++ /* ++ * Block a timer-based transmit from overlapping. This could better be ++ * done with atomic_swap(1, dev->tbusy), but set_bit() works as well. ++ */ ++ ++ if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) { ++ printk(KERN_WARNING "%s: Transmitter access conflict.\n", ++ dev->name); ++ } else { ++ DPRINTK("skbuff head:%lx data:%lx tail:%lx end:%lx\n", ++ (long)skb->head, (long)skb->data, (long)skb->tail, ++ (long)skb->end); ++ ++ /* Put le header to place */ ++ lec_h = (struct lecdatahdr_8023*)skb->data; ++ /* ++ lec_h->le_header = htons(priv->lecid); ++ */ ++#if DUMP_PACKETS > 0 ++ printk("%s: send datalen:%ld lecid:%4.4x\n", dev->name, ++ skb->len, priv->lecid); ++#if DUMP_PACKETS >= 2 ++ for(i=0;ilen && i <99;i++) { ++ sprintf(buf+i*3,"%2.2x ",0xff&skb->data[i]); ++ } ++#elif DUMP_PACKETS >= 1 ++ for(i=0;ilen && i < 30;i++) { ++ sprintf(buf+i*3,"%2.2x ", 0xff&skb->data[i]); ++ } ++#endif /* DUMP_PACKETS >= 1 */ ++ if (i==skb->len) ++ printk("%s\n",buf); ++ else ++ printk("%s...\n",buf); ++#endif /* DUMP_PACKETS > 0 */ ++ /* Send to right vcc */ ++ send_vcc = lec_arp_resolve(priv, lec_h->h_dest); ++ DPRINTK("%s:send_vcc:%p vcc_flags:%x\n", dev->name, ++ send_vcc, send_vcc?send_vcc->flags:0); ++ if (!send_vcc || !(send_vcc->flags & ATM_VF_READY)) { ++ priv->stats.tx_dropped++; ++ printk("%s:lec_send_packet: bad vcc, dropping packet...\n", ++ dev->name); ++ dev_kfree_skb(skb, FREE_WRITE); /* like in clip.c */ ++ dev->tbusy=0; ++ return 0; ++ } else { ++#if DUMP_PACKETS > 0 ++ printk("%s:sending to vpi:%d vci:%d\n", dev->name, ++ send_vcc->vpi, send_vcc->vci); ++#endif /* DUMP_PACKETS > 0 */ ++ skb->atm.vcc = send_vcc; ++ /* Minimum ethernet-frame size */ ++ if (skb->len <62) { ++ if (skb->truesize < 62) { ++ printk("%s:data packet %d / %d\n", ++ dev->name, ++ skb->len,skb->truesize); ++ nb=(unsigned char*)kmalloc(64, ++ GFP_ATOMIC); ++ memcpy(nb,skb->data,skb->len); ++ kfree(skb->head); ++ skb->head = skb->data = nb; ++ skb->tail = nb+62; ++ skb->end = nb+64; ++ skb->len=62; ++ skb->truesize = 64; ++ } else { ++ skb->len = 62; ++ } ++ } ++ atomic_add(skb->truesize, &send_vcc->tx_inuse); ++ skb->atm.iovcnt = 0; ++ send_vcc->dev->ops->send(send_vcc, skb); ++ priv->stats.tx_packets++; ++ } ++ } ++ /* Should we wait for card's device driver to notify us? */ ++ dev->tbusy=0; ++ ++ return 0; ++} ++ ++/* The inverse routine to net_open(). */ ++static int ++lec_close(struct device *dev) ++{ ++ dev->tbusy = 1; ++ dev->start = 0; ++ return 0; ++} ++ ++/* ++ * Get the current statistics. ++ * This may be called with the card open or closed. ++ */ ++static struct enet_statistics * ++lec_get_stats(struct device *dev) ++{ ++ struct lec_priv *priv = (struct lec_priv *)dev->priv; ++ ++ return (struct enet_statistics *)&priv->stats; ++} ++ ++int ++lec_hard_header(struct sk_buff *skb, struct device *dev, ++ unsigned short type, void *daddr, void *saddr, ++ unsigned len) ++{ ++ struct lec_priv *priv = (struct lec_priv *)dev->priv; ++ struct lecdatahdr_8023 *hdr = ++ (struct lecdatahdr_8023 *)skb_push(skb, LEC_HEADER_LEN); ++ ++ /* Set lecid header */ ++ if (priv) ++ hdr->le_header = htons(priv->lecid); ++ else ++ hdr->le_header = 0; ++ ++ /* Set the protocol type. */ ++ if(type!=ETH_P_802_3) ++ hdr->h_type = htons(type); ++ else ++ hdr->h_type = htons(len); ++ ++ /* Source hw address */ ++ if (saddr) ++ memcpy(hdr->h_source, saddr, dev->addr_len); ++ else ++ memcpy(hdr->h_source, dev->dev_addr, dev->addr_len); ++ ++ /* Destination addr */ ++ if (daddr) { ++ memcpy(hdr->h_dest, daddr, dev->addr_len); ++ return dev->hard_header_len; ++ } ++ return -dev->hard_header_len; ++} ++ ++int ++lec_rebuild_header(struct sk_buff *skb) ++{ ++ struct lecdatahdr_8023 *hdr = (struct lecdatahdr_8023*)skb->data; ++ struct device *dev = skb->dev; ++ ++ switch (hdr->h_type) ++ { ++#ifdef CONFIG_INET ++ case __constant_htons(ETH_P_IP): ++ return arp_find(hdr->h_dest, skb); ++#endif ++ default: ++ printk(KERN_DEBUG ++ "%s: unable to resolve type %X addresses.\n", ++ dev->name, (int)hdr->h_type); ++ ++ memcpy(hdr->h_source, dev->dev_addr, dev->addr_len); ++ return 0; ++ break; ++ } ++ ++ return 0; ++} ++ ++/* ++ * Called by Address Resolution module to notify changes in address. ++ */ ++void ++lec_header_cache_update(struct hh_cache *hh, struct device *dev, ++ unsigned char *haddr) ++{ ++ u16 *u16ptr = (u16 *)hh->hh_data; ++ ++ if (hh->hh_type != ETH_P_IP) { ++ printk("lec_header_cache_update: %04x cache is not implemented\n", ++ hh->hh_type); ++ return; ++ } ++ memcpy(u16ptr+1, haddr, ETH_ALEN); ++} ++ ++static int ++lec_atm_send(struct atm_vcc *vcc, struct sk_buff *skb) ++{ ++ struct device *dev = (struct device*)vcc->proto_data; ++ struct lec_priv *priv = (struct lec_priv*)dev->priv; ++ struct atmlec_msg *mesg; ++ int i; ++ ++ atomic_sub(skb->truesize+ATM_PDU_OVHD, &vcc->tx_inuse); ++ mesg = (struct atmlec_msg *)skb->data; ++ DPRINTK("%s: msg from zeppelin:%d\n", dev->name, mesg->type); ++ switch(mesg->type) { ++ case l_set_mac_addr: ++ for (i=0;i<6;i++) { ++ dev->dev_addr[i] = mesg->content.normal.mac_addr[i]; ++ } ++ break; ++ case l_del_mac_addr: ++ for(i=0;i<6;i++) { ++ dev->dev_addr[i] = 0; ++ } ++ break; ++ case l_addr_delete: ++ lec_addr_delete(priv, mesg->content.normal.atm_addr, ++ mesg->content.normal.flag); ++ break; ++ case l_topology_change: ++ priv->topology_change = mesg->content.normal.flag; ++ break; ++ case l_flush_complete: ++ lec_flush_complete(priv, mesg->content.normal.flag); ++ break; ++ case l_arp_update: ++ lec_arp_update(priv, mesg->content.normal.mac_addr, ++ mesg->content.normal.atm_addr, ++ mesg->content.normal.flag); ++ if (mesg->sizeoftlvs != 0) { /* LANE2 3.1.5 */ ++ printk("lec: LANE2 3.1.5, got tlvs\n"); ++ lane2_associate_ind(priv, ++ mesg->content.normal.mac_addr, ++ (u8 *)mesg+1, mesg->sizeoftlvs); ++ } ++ break; ++ case l_config: ++ priv->maximum_unknown_frame_count = ++ mesg->content.config.maximum_unknown_frame_count; ++ priv->max_unknown_frame_time = ++ (mesg->content.config.max_unknown_frame_time*HZ); ++ priv->max_retry_count = ++ mesg->content.config.max_retry_count; ++ priv->aging_time = (mesg->content.config.aging_time*HZ); ++ priv->forward_delay_time = ++ (mesg->content.config.forward_delay_time*HZ); ++ priv->arp_response_time = ++ (mesg->content.config.arp_response_time*HZ); ++ priv->flush_timeout = (mesg->content.config.flush_timeout*HZ); ++ priv->path_switching_delay = ++ (mesg->content.config.path_switching_delay*HZ); ++ break; ++ case l_flush_tran_id: ++ lec_set_flush_tran_id(priv, mesg->content.normal.atm_addr, ++ mesg->content.normal.flag); ++ break; ++ case l_set_lecid: ++ priv->lecid=(unsigned short)(0xffff&mesg->content.normal.flag); ++ break; ++ default: ++ printk("%s: Unknown message type %d\n", dev->name, mesg->type); ++ dev_kfree_skb(skb, FREE_WRITE); ++ return -EINVAL; ++ } ++ dev_kfree_skb(skb, FREE_WRITE); ++ return 0; ++} ++ ++static void ++lec_atm_close(struct atm_vcc *vcc) ++{ ++ struct sk_buff *skb; ++ struct device *dev = (struct device *)vcc->proto_data; ++ struct lec_priv *priv = (struct lec_priv *)dev->priv; ++ ++ priv->lecd = NULL; ++ /* Do something needful? */ ++ ++ dev->tbusy = 1; ++ dev->start = 0; ++ ++ lec_arp_destroy(priv); ++ ++ if (skb_peek(&vcc->recvq)) ++ printk("%s lec_atm_close: closing with messages pending\n", ++ dev->name); ++ while ((skb = skb_dequeue(&vcc->recvq))) { ++ dev_kfree_skb(skb,FREE_READ); ++ atm_return(vcc, skb->truesize); ++ } ++ ++ printk("%s: Shut down!\n", dev->name); ++ MOD_DEC_USE_COUNT; ++} ++ ++static struct atmdev_ops lecdev_ops = { ++ NULL, /*dev_close*/ ++ NULL, /*open*/ ++ lec_atm_close, /*close*/ ++ NULL, /*ioctl*/ ++ NULL, /*getsockopt */ ++ NULL, /*setsockopt */ ++ lec_atm_send, /*send */ ++ NULL, /*sg_send */ ++#if 0 /* these are disabled in too */ ++ NULL, /*poll */ ++ NULL, /*send_iovec*/ ++#endif ++ NULL, /*send_oam*/ ++ NULL, /*phy_put*/ ++ NULL, /*phy_get*/ ++ NULL, /*feedback*/ ++ NULL, /* change_qos*/ ++ NULL /* free_rx_skb*/ ++}; ++ ++static struct atm_dev lecatm_dev = { ++ &lecdev_ops, ++ NULL, /*PHY*/ ++ "lec", /*type*/ ++ 999, /*dummy device number*/ ++ NULL,NULL, /*no VCCs*/ ++ NULL,NULL, /*no data*/ ++ 0, /*no flags*/ ++ NULL, /* no local address*/ ++ { 0 } /*no ESI or rest of the atm_dev struct things*/ ++}; ++ ++/* ++ * LANE2: new argument struct sk_buff *data contains ++ * the LE_ARP based TLVs introduced in the LANE2 spec ++ */ ++int ++send_to_lecd(struct lec_priv *priv, atmlec_msg_type type, ++ unsigned char *mac_addr, unsigned char *atm_addr, ++ struct sk_buff *data) ++{ ++ struct sk_buff *skb; ++ struct atmlec_msg *mesg; ++ ++ if (!priv || !priv->lecd) { ++ return -1; ++ } ++ skb = alloc_skb(sizeof(struct atmlec_msg), GFP_ATOMIC); ++ if (!skb) ++ return -1; ++ skb->len = sizeof(struct atmlec_msg); ++ mesg = (struct atmlec_msg *)skb->data; ++ memset(mesg, 0, sizeof(struct atmlec_msg)); ++ mesg->type = type; ++ if (mac_addr) ++ memcpy(&mesg->content.normal.mac_addr, mac_addr, ETH_ALEN); ++ if (atm_addr) ++ memcpy(&mesg->content.normal.atm_addr, atm_addr, ATM_ESA_LEN); ++ ++ if (atm_charge(priv->lecd, skb->truesize) == 0) ++ DPRINTK("lec: send_to_lecd, atm_charge()\n"); ++ skb_queue_tail(&priv->lecd->recvq, skb); ++ wake_up(&priv->lecd->sleep); ++ ++ if (data != NULL) { ++ printk("lec: about to send %d bytes of data\n", data->len); ++ mesg->sizeoftlvs = data->len; ++ if (atm_charge(priv->lecd, data->truesize) == 0) ++ DPRINTK("lec: send_to_lecd, atm_charge()\n"); ++ skb_queue_tail(&priv->lecd->recvq, data); ++ wake_up(&priv->lecd->sleep); ++ } ++ ++ return 0; ++} ++ ++static int ++lec_init(struct device *dev) ++{ ++ dev->priv = kmalloc(sizeof(struct lec_priv), GFP_KERNEL); ++ if (!dev->priv) ++ return -ENOMEM; ++ ++ memset(dev->priv,0,sizeof(struct lec_priv)); ++ ++ ether_setup(dev); ++ dev->hard_header = lec_hard_header; ++ dev->rebuild_header = lec_rebuild_header; ++ dev->hard_header_cache = NULL; ++ dev->header_cache_update = lec_header_cache_update; ++ dev->open = lec_open; ++ dev->stop = lec_close; ++ dev->hard_start_xmit = lec_send_packet; ++ dev->hard_header_len = LEC_HEADER_LEN; ++ ++ dev->get_stats = lec_get_stats; ++ dev->set_multicast_list = NULL; ++ dev->do_ioctl = NULL; ++ printk("%s: Initialized!\n",dev->name); ++ return 0; ++} ++ ++static unsigned char lec_ctrl_magic[] = { ++ 0xff, ++ 0x00, ++ 0x01, ++ 0x01 }; ++ ++void ++lec_push(struct atm_vcc *vcc, struct sk_buff *skb) ++{ ++ struct device *dev = (struct device *)vcc->proto_data; ++ struct lec_priv *priv = (struct lec_priv *)dev->priv; ++ struct lecdatahdr_8023 *hdr; ++ unsigned char *rawp; ++#if DUMP_PACKETS >0 ++ int i=0; ++ char buf[300]; ++ ++ printk("%s: lec_push vcc vpi:%d vci:%d\n", dev->name, ++ vcc->vpi, vcc->vci); ++#endif ++ if (!skb) { ++ DPRINTK("%s: null skb\n",dev->name); ++ lec_vcc_close(priv, vcc); ++ return; ++ } ++#if DUMP_PACKETS > 0 ++ printk("%s: rcv datalen:%ld lecid:%4.4x\n", dev->name, ++ skb->len, priv->lecid); ++#if DUMP_PACKETS >= 2 ++ for(i=0;ilen && i <99;i++) { ++ sprintf(buf+i*3,"%2.2x ",0xff&skb->data[i]); ++ } ++#elif DUMP_PACKETS >= 1 ++ for(i=0;ilen && i < 30;i++) { ++ sprintf(buf+i*3,"%2.2x ", 0xff&skb->data[i]); ++ } ++#endif /* DUMP_PACKETS >= 1 */ ++ if (i==skb->len) ++ printk("%s\n",buf); ++ else ++ printk("%s...\n",buf); ++#endif /* DUMP_PACKETS > 0 */ ++ if (memcmp(skb->data, lec_ctrl_magic, 4) ==0) { /* Control frame, to daemon*/ ++ DPRINTK("%s: To daemon\n",dev->name); ++ skb_queue_tail(&vcc->recvq, skb); ++ wake_up(&vcc->sleep); ++ } else { /* Data frame, queue to protocol handlers */ ++ atm_return(vcc,skb->truesize); ++ hdr = (struct lecdatahdr_8023 *)skb->data; ++ if (hdr->le_header == htons(priv->lecid) || ++ !priv->lecd) { ++ /* Probably looping back, or if lecd is missing, ++ lecd has gone down */ ++ DPRINTK("Ignoring loopback frame...\n"); ++ dev_kfree_skb(skb, FREE_READ); ++ return; ++ } ++ if (priv->lec_arp_empty_ones) { /* FILTER DATA!!!! */ ++ lec_arp_check_empties(priv, vcc, skb); ++ } ++ skb->dev = dev; ++ skb->mac.raw = (unsigned char *)skb->data; ++ if (*hdr->h_dest&1) { ++ if (memcmp(hdr->h_dest,dev->broadcast, ETH_ALEN)==0) ++ skb->pkt_type=PACKET_BROADCAST; ++ else ++ skb->pkt_type=PACKET_MULTICAST; ++ } else if (dev->flags&(IFF_PROMISC|IFF_ALLMULTI)) { ++ if (memcmp(hdr->h_dest,dev->dev_addr, ETH_ALEN)) ++ skb->pkt_type=PACKET_OTHERHOST; ++ } ++ if (ntohs(hdr->h_type)>=1536) ++ skb->protocol = hdr->h_type; ++ else ++ skb->protocol = htons(ETH_P_802_2); ++ skb->h.raw = skb_pull(skb, LEC_HEADER_LEN); ++ rawp = skb->data; ++ /* Magic hack for IPX ... */ ++ if (*(unsigned short*)rawp == 0xFFFF) ++ skb->protocol = htons(ETH_P_802_3); ++ netif_rx(skb); ++ priv->stats.rx_packets++; ++ } ++} ++ ++int ++lec_vcc_attach(struct atm_vcc *vcc, void *arg) ++{ ++ int bytes_left; ++ struct atmlec_ioc ioc_data; ++ ++ /* Lecd must be up in this case */ ++ bytes_left = copy_from_user(&ioc_data, arg, sizeof(struct atmlec_ioc)); ++ if (bytes_left != 0) { ++ printk("lec: lec_vcc_attach, copy from user failed for %d bytes\n", ++ bytes_left); ++ } ++ if (ioc_data.dev_num < 0 || ioc_data.dev_num >= MAX_LEC_ITF || ++ !dev_lec[ioc_data.dev_num]) ++ return -EINVAL; ++ lec_vcc_added(dev_lec[ioc_data.dev_num]->priv, ++ &ioc_data, vcc, vcc->push); ++ vcc->push = lec_push; ++ vcc->proto_data = dev_lec[ioc_data.dev_num]; ++ return 0; ++} ++ ++int ++lec_mcast_attach(struct atm_vcc *vcc, int arg) ++{ ++ if (arg <0 || arg >= MAX_LEC_ITF || !dev_lec[arg]) ++ return -EINVAL; ++ vcc->proto_data = dev_lec[arg]; ++ return (lec_mcast_make((struct lec_priv*)dev_lec[arg]->priv, vcc)); ++} ++ ++/* Initialize device. */ ++int ++lecd_attach(struct atm_vcc *vcc, int arg) ++{ ++ int i, result; ++ struct lec_priv *priv; ++ ++ if (arg<0) ++ i = 0; ++ else ++ i = arg; ++ if (arg >= MAX_LEC_ITF) ++ return -EINVAL; ++ if (!dev_lec[i]) { ++ dev_lec[i] = (struct device*)kmalloc(sizeof(struct device)+ ++ sizeof(myname)+1, ++ GFP_KERNEL); ++ if (!dev_lec[i]) ++ return -ENOMEM; ++ memset(dev_lec[i],0, sizeof(struct device)+sizeof(myname)+1); ++ dev_lec[i]->name = (char*)(dev_lec[i]+1); ++ sprintf(dev_lec[i]->name, "lec%d",i); ++ dev_lec[i]->init = lec_init; ++ if ((result = register_netdev(dev_lec[i])) !=0) ++ return result; ++ priv = (struct lec_priv *)dev_lec[i]->priv; ++ } else { ++ priv = (struct lec_priv *)dev_lec[i]->priv; ++ if (priv->lecd) ++ return -EADDRINUSE; ++ } ++ lec_arp_init(priv); ++ priv->lecd = vcc; ++ vcc->dev = &lecatm_dev; ++ ++ vcc->proto_data = dev_lec[i]; ++ vcc->flags |= ATM_VF_READY | ATM_VF_META; ++ ++ /* Set default values to these variables */ ++ priv->maximum_unknown_frame_count = 1; ++ priv->max_unknown_frame_time = (1*HZ); ++ priv->vcc_timeout_period = (1200*HZ); ++ priv->max_retry_count = 1; ++ priv->aging_time = (300*HZ); ++ priv->forward_delay_time = (15*HZ); ++ priv->topology_change = 0; ++ priv->arp_response_time = (1*HZ); ++ priv->flush_timeout = (4*HZ); ++ priv->path_switching_delay = (6*HZ); ++ ++ if (dev_lec[i]->flags & IFF_UP) { ++ dev_lec[i]->tbusy = 0; ++ dev_lec[i]->start = 1; ++ printk("lec.c: lecd_attach() upping device\n"); ++ } ++ MOD_INC_USE_COUNT; ++ return i; ++} ++ ++#ifdef MODULE ++#include ++extern void atm_lane_setup (int (*attach)(struct atm_vcc *vcc, int arg), ++ int (*mcast)(struct atm_vcc *vcc, int arg), ++ int (*vcc)(struct atm_vcc *vcc, void *arg), ++ struct device **(*dev_lec_ptr)(void)); ++#ifndef LEC_VERSION ++#define LEC_VERSION "0.34" ++#endif ++ ++int init_module(void) ++{ ++ printk("lec.c: v. %s.\n", LEC_VERSION); ++ ++ atm_lane_setup(lecd_attach, lec_mcast_attach, ++ lec_vcc_attach, get_dev_lec); ++ return 0; ++} ++ ++void cleanup_module(void) ++{ ++ if (MOD_IN_USE) { ++ printk(KERN_NOTICE "lec: Device busy, remove delayed.\n"); ++ } ++ else { ++ int i; ++ atm_lane_setup(NULL, NULL, NULL, NULL); ++ for (i = 0; i < MAX_LEC_ITF; i++) { ++ if (dev_lec[i] != NULL) { ++ unregister_netdev(dev_lec[i]); ++ kfree(dev_lec[i]->priv); ++ kfree(dev_lec[i]); ++ dev_lec[i] = NULL; ++ } ++ } ++ return; ++ } ++} ++ ++#endif /* MODULE */ ++ ++/* ++ * LANE2: 3.1.3, LE_RESOLVE.request ++ * Non force allocates memory and fills in *tlvs, fills in *sizeoftlvs. ++ */ ++int lane2_resolve(u8 *dst_mac, int force, struct device *dev, u8 **tlvs, u32 *sizeoftlvs) ++{ ++ struct lec_priv *priv = (struct lec_priv *)dev->priv; ++ struct lec_arp_table *table; ++ struct sk_buff *skb; ++ int retval; ++ ++ if (force == 0) { ++ table = lec_arp_find(priv, dst_mac); ++ if(table == NULL) ++ return -1; ++ ++ *tlvs = kmalloc(table->sizeoftlvs, GFP_KERNEL); ++ if (*tlvs == NULL) ++ return -1; ++ ++ memcpy(*tlvs, table->tlvs, table->sizeoftlvs); ++ *sizeoftlvs = table->sizeoftlvs; ++ ++ return 0; ++ } ++ ++ skb = alloc_skb(*sizeoftlvs, GFP_ATOMIC); ++ if (skb == NULL) ++ return -1; ++ skb->len = *sizeoftlvs; ++ memcpy(skb->data, *tlvs, *sizeoftlvs); ++ retval = send_to_lecd(priv, l_arp_xmt, dst_mac, NULL, skb); ++ ++ return retval; ++} ++ ++ ++/* ++ * LANE2: 3.1.4, LE_ASSOCIATE.request ++ * Associate the *tlvs with the *lan_dst address. ++ * Will overwrite any previous association ++ * Returns 1 for success, 0 for fail (out of memory, wrong lan_dst) ++ * ++ * Do we need to check the arp table for *lan_dst? ++ */ ++int lane2_associate_req (struct device *dev, u8 *lan_dst, ++ u8 *tlvs, u32 sizeoftlvs) ++{ ++ struct lec_priv *priv = (struct lec_priv*)dev->priv; ++ ++ if ( memcmp(lan_dst, dev->dev_addr, 6) != 0 ) ++ return (0); /* not our mac address */ ++ ++ kfree(priv->tlvs); /* NULL if there was no previous association */ ++ ++ priv->tlvs = kmalloc(sizeoftlvs, GFP_KERNEL); ++ if (priv->tlvs == NULL) ++ return (0); ++ priv->sizeoftlvs = sizeoftlvs; ++ memcpy(priv->tlvs, tlvs, sizeoftlvs); ++ ++ /* If the previous association has changed we must ++ * somehow notify other LANE entities about the change ++ */ ++ return (1); ++} ++ ++/* ++ * LANE2: 3.1.5, LE_ASSOCIATE.indication ++ * ++ */ ++void lane2_associate_ind (struct lec_priv *priv, u8 *mac_addr, u8 *tlvs, u32 sizeoftlvs) ++{ ++ int i = 0; ++ struct lec_arp_table *entry = lec_arp_find(priv, mac_addr); ++ ++ if (entry == NULL) ++ return; /* should not happen */ ++ ++ kfree(entry->tlvs); ++ ++ entry->tlvs = kmalloc(sizeoftlvs, GFP_KERNEL); ++ if (entry->tlvs == NULL) ++ return; ++ ++ entry->sizeoftlvs = sizeoftlvs; ++ memcpy(entry->tlvs, tlvs, sizeoftlvs); ++ ++ printk("lec.c: lane2_associate_ind() associated\n "); ++ printk("dump of tlvs, sizeoftlvs=%d\n", sizeoftlvs); ++ while (i < sizeoftlvs) ++ printk("%02x ", tlvs[i++]); ++ ++ printk("\n"); ++ ++ ++ ++ ++ ++ ++ return; ++} ++ ++/* ++ * Here starts what used to lec_arpc.c ++ * ++ * lec_arpc.c was added here when making ++ * lane client modular. October 1997 ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++ ++#if 0 ++#define DPRINTK(format,args...) ++/* ++#define DPRINTK printk ++*/ ++#endif ++#define DEBUG_ARP_TABLE 0 ++ ++#define LEC_ARP_REFRESH_INTERVAL (3*HZ) ++ ++static void lec_arp_check_expire(unsigned long data); ++static __inline__ void lec_arp_expire_arp(unsigned long data); ++void dump_arp_table(struct lec_priv *priv); ++ ++/* ++ * Arp table funcs ++ */ ++ ++#define HASH(ch) (ch & (LEC_ARP_TABLE_SIZE -1)) ++ ++static __inline__ void ++lec_arp_lock(struct lec_priv *priv) ++{ ++ atomic_inc(&priv->lec_arp_lock_var); ++} ++ ++static __inline__ void ++lec_arp_unlock(struct lec_priv *priv) ++{ ++ atomic_dec(&priv->lec_arp_lock_var); ++} ++ ++/* ++ * Initialization of arp-cache ++ */ ++void ++lec_arp_init(struct lec_priv *priv) ++{ ++ unsigned short i; ++ ++ for (i=0;ilec_arp_tables[i] = NULL; ++ } ++ init_timer(&priv->lec_arp_timer); ++ priv->lec_arp_timer.expires = jiffies+LEC_ARP_REFRESH_INTERVAL; ++ priv->lec_arp_timer.data = (unsigned long)priv; ++ priv->lec_arp_timer.function = lec_arp_check_expire; ++ add_timer(&priv->lec_arp_timer); ++} ++ ++void ++lec_arp_clear_vccs(struct lec_arp_table *entry) ++{ ++ if (entry->vcc) { ++ entry->vcc->push = entry->old_push; ++ entry->vcc->flags |= ATM_VF_RELEASED; ++ entry->vcc->flags &= ~ATM_VF_READY; ++ entry->vcc = NULL; ++ } ++ if (entry->recv_vcc) { ++ entry->recv_vcc->push = entry->old_recv_push; ++ entry->recv_vcc->flags |= ATM_VF_RELEASED; ++ entry->recv_vcc->flags &= ~ATM_VF_READY; ++ entry->recv_vcc = NULL; ++ } ++} ++ ++/* ++ * Insert entry to lec_arp_table ++ */ ++static __inline__ void ++lec_arp_put(struct lec_arp_table **lec_arp_tables, ++ struct lec_arp_table *to_put) ++{ ++ unsigned short place; ++ unsigned long flags; ++ ++ save_flags(flags); ++ cli(); ++ ++ place = HASH(to_put->mac_addr[ETH_ALEN-1]); ++ to_put->next = lec_arp_tables[place]; ++ lec_arp_tables[place] = to_put; ++ ++ restore_flags(flags); ++ DPRINTK("LEC_ARP: Added entry:%2.2x %2.2x %2.2x %2.2x %2.2x %2.2x\n", ++ 0xff&to_put->mac_addr[0], 0xff&to_put->mac_addr[1], ++ 0xff&to_put->mac_addr[2], 0xff&to_put->mac_addr[3], ++ 0xff&to_put->mac_addr[4], 0xff&to_put->mac_addr[5]); ++} ++ ++/* ++ * Remove entry from lec_arp_table ++ */ ++static __inline__ int ++lec_arp_remove(struct lec_arp_table **lec_arp_tables, ++ struct lec_arp_table *to_remove) ++{ ++ unsigned short place; ++ struct lec_arp_table *tmp; ++ unsigned long flags; ++ int remove_vcc=1; ++ ++ save_flags(flags); ++ cli(); ++ ++ if (!to_remove) { ++ restore_flags(flags); ++ return -1; ++ } ++ place = HASH(to_remove->mac_addr[ETH_ALEN-1]); ++ tmp = lec_arp_tables[place]; ++ if (tmp == to_remove) { ++ lec_arp_tables[place] = tmp->next; ++ } else { ++ while(tmp && tmp->next != to_remove) { ++ tmp = tmp->next; ++ } ++ if (!tmp) {/* Entry was not found */ ++ restore_flags(flags); ++ return -1; ++ } ++ } ++ tmp->next = to_remove->next; ++ del_timer(&to_remove->timer); ++ ++ /* If this is the only MAC connected to this VCC, also tear down ++ the VCC */ ++ if (to_remove->status >= ESI_FLUSH_PENDING) { ++ /* ++ * ESI_FLUSH_PENDING, ESI_FORWARD_DIRECT ++ */ ++ for(place=0;placenext){ ++ if (memcmp(tmp->atm_addr, to_remove->atm_addr, ++ ATM_ESA_LEN)==0) { ++ remove_vcc=0; ++ break; ++ } ++ } ++ } ++ if (remove_vcc) ++ lec_arp_clear_vccs(to_remove); ++ } ++ restore_flags(flags); ++ DPRINTK("LEC_ARP: Removed entry:%2.2x %2.2x %2.2x %2.2x %2.2x %2.2x\n", ++ 0xff&to_remove->mac_addr[0], 0xff&to_remove->mac_addr[1], ++ 0xff&to_remove->mac_addr[2], 0xff&to_remove->mac_addr[3], ++ 0xff&to_remove->mac_addr[4], 0xff&to_remove->mac_addr[5]); ++ ++ return 0; ++} ++ ++#if DEBUG_ARP_TABLE ++static char* ++get_status_string(unsigned char st) ++{ ++ switch(st) { ++ case ESI_UNKNOWN: ++ return "ESI_UNKNOWN"; ++ case ESI_ARP_PENDING: ++ return "ESI_ARP_PENDING"; ++ case ESI_VC_PENDING: ++ return "ESI_VC_PENDING"; ++ case ESI_FLUSH_PENDING: ++ return "ESI_FLUSH_PENDING"; ++ case ESI_FORWARD_DIRECT: ++ return "ESI_FORWARD_DIRECT"; ++ default: ++ return ""; ++ } ++} ++#endif ++ ++void ++dump_arp_table(struct lec_priv *priv) ++{ ++#if DEBUG_ARP_TABLE ++ int i,j, offset; ++ struct lec_arp_table *rulla; ++ char buf[1024]; ++ struct lec_arp_table **lec_arp_tables = ++ (struct lec_arp_table **)priv->lec_arp_tables; ++ struct lec_arp_table *lec_arp_empty_ones = ++ (struct lec_arp_table *)priv->lec_arp_empty_ones; ++ struct lec_arp_table *lec_no_forward = ++ (struct lec_arp_table *)priv->lec_no_forward; ++ ++ printk("Dump %p:\n",priv); ++ for (i=0;imac_addr[j]&0xff); ++ } ++ offset +=sprintf(buf+offset,"Atm:"); ++ for(j=0;jatm_addr[j]&0xff); ++ } ++ offset+=sprintf(buf+offset, ++ "Vcc vpi:%d vci:%d, Recv_vcc vpi:%d vci:%d Last_used:%lx, Timestamp:%lx, No_tries:%d ", ++ rulla->vcc?rulla->vcc->vpi:0, ++ rulla->vcc?rulla->vcc->vci:0, ++ rulla->recv_vcc?rulla->recv_vcc->vpi:0, ++ rulla->recv_vcc?rulla->recv_vcc->vci:0, ++ rulla->last_used, ++ rulla->timestamp, rulla->no_tries); ++ offset+=sprintf(buf+offset, ++ "Flags:%x, Packets_flooded:%x, Status: %s ", ++ rulla->flags, rulla->packets_flooded, ++ get_status_string(rulla->status)); ++ offset+=sprintf(buf+offset,"->%p\n",rulla->next); ++ rulla = rulla->next; ++ } ++ printk("%s",buf); ++ } ++ rulla = lec_no_forward; ++ if (rulla) ++ printk("No forward\n"); ++ while(rulla) { ++ offset=0; ++ offset += sprintf(buf+offset,"Mac:"); ++ for(j=0;jmac_addr[j]&0xff); ++ } ++ offset +=sprintf(buf+offset,"Atm:"); ++ for(j=0;jatm_addr[j]&0xff); ++ } ++ offset+=sprintf(buf+offset, ++ "Vcc vpi:%d vci:%d, Recv_vcc vpi:%d vci:%d Last_used:%lx, Timestamp:%lx, No_tries:%d ", ++ rulla->vcc?rulla->vcc->vpi:0, ++ rulla->vcc?rulla->vcc->vci:0, ++ rulla->recv_vcc?rulla->recv_vcc->vpi:0, ++ rulla->recv_vcc?rulla->recv_vcc->vci:0, ++ rulla->last_used, ++ rulla->timestamp, rulla->no_tries); ++ offset+=sprintf(buf+offset, ++ "Flags:%x, Packets_flooded:%x, Status: %s ", ++ rulla->flags, rulla->packets_flooded, ++ get_status_string(rulla->status)); ++ offset+=sprintf(buf+offset,"->%lx\n",(long)rulla->next); ++ rulla = rulla->next; ++ printk("%s",buf); ++ } ++ rulla = lec_arp_empty_ones; ++ if (rulla) ++ printk("Empty ones\n"); ++ while(rulla) { ++ offset=0; ++ offset += sprintf(buf+offset,"Mac:"); ++ for(j=0;jmac_addr[j]&0xff); ++ } ++ offset +=sprintf(buf+offset,"Atm:"); ++ for(j=0;jatm_addr[j]&0xff); ++ } ++ offset+=sprintf(buf+offset, ++ "Vcc vpi:%d vci:%d, Recv_vcc vpi:%d vci:%d Last_used:%lx, Timestamp:%lx, No_tries:%d ", ++ rulla->vcc?rulla->vcc->vpi:0, ++ rulla->vcc?rulla->vcc->vci:0, ++ rulla->recv_vcc?rulla->recv_vcc->vpi:0, ++ rulla->recv_vcc?rulla->recv_vcc->vci:0, ++ rulla->last_used, ++ rulla->timestamp, rulla->no_tries); ++ offset+=sprintf(buf+offset, ++ "Flags:%x, Packets_flooded:%x, Status: %s ", ++ rulla->flags, rulla->packets_flooded, ++ get_status_string(rulla->status)); ++ offset+=sprintf(buf+offset,"->%lx\n",(long)rulla->next); ++ rulla = rulla->next; ++ printk("%s",buf); ++ } ++ ++#endif ++} ++ ++/* ++ * Destruction of arp-cache ++ */ ++void ++lec_arp_destroy(struct lec_priv *priv) ++{ ++ struct lec_arp_table *entry, *next; ++ unsigned long flags; ++ int i; ++ ++ save_flags(flags); ++ cli(); ++ ++ del_timer(&priv->lec_arp_timer); ++ ++ /* ++ * Remove all entries ++ */ ++ for (i=0;ilec_arp_tables[i];entry != NULL; entry=next) { ++ next = entry->next; ++ lec_arp_remove(priv->lec_arp_tables, entry); ++ kfree(entry); ++ } ++ } ++ entry = priv->lec_arp_empty_ones; ++ while(entry) { ++ next = entry->next; ++ del_timer(&entry->timer); ++ lec_arp_clear_vccs(entry); ++ kfree(entry); ++ entry = next; ++ } ++ priv->lec_arp_empty_ones = NULL; ++ entry = priv->lec_no_forward; ++ while(entry) { ++ next = entry->next; ++ del_timer(&entry->timer); ++ lec_arp_clear_vccs(entry); ++ kfree(entry); ++ entry = next; ++ } ++ priv->lec_no_forward = NULL; ++ priv->mcast_vcc = NULL; ++ memset(priv->lec_arp_tables, 0, ++ sizeof(struct lec_arp_table*)*LEC_ARP_TABLE_SIZE); ++ restore_flags(flags); ++} ++ ++ ++/* ++ * Find entry by mac_address ++ */ ++static __inline__ struct lec_arp_table* ++lec_arp_find(struct lec_priv *priv, ++ unsigned char *mac_addr) ++{ ++ unsigned short place; ++ struct lec_arp_table *to_return; ++ ++ DPRINTK("LEC_ARP: lec_arp_find :%2.2x %2.2x %2.2x %2.2x %2.2x %2.2x\n", ++ mac_addr[0]&0xff, mac_addr[1]&0xff, mac_addr[2]&0xff, ++ mac_addr[3]&0xff, mac_addr[4]&0xff, mac_addr[5]&0xff); ++ lec_arp_lock(priv); ++ place = HASH(mac_addr[ETH_ALEN-1]); ++ ++ to_return = priv->lec_arp_tables[place]; ++ while(to_return) { ++ if (memcmp(mac_addr, to_return->mac_addr, ETH_ALEN) == 0) { ++ lec_arp_unlock(priv); ++ return to_return; ++ } ++ to_return = to_return->next; ++ } ++ lec_arp_unlock(priv); ++ return NULL; ++} ++ ++static struct lec_arp_table* ++make_entry(struct lec_priv *priv, unsigned char *mac_addr) ++{ ++ struct lec_arp_table *to_return; ++ ++ to_return=(struct lec_arp_table *)kmalloc(sizeof(struct lec_arp_table), ++ GFP_ATOMIC); ++ if (!to_return) { ++ printk("LEC: Arp entry kmalloc failed\n"); ++ return NULL; ++ } ++ memset(to_return,0,sizeof(struct lec_arp_table)); ++ memcpy(to_return->mac_addr, mac_addr, ETH_ALEN); ++ init_timer(&to_return->timer); ++ to_return->timer.function = lec_arp_expire_arp; ++ to_return->timer.data = (unsigned long)to_return; ++ to_return->last_used = jiffies; ++ to_return->priv = priv; ++ return to_return; ++} ++ ++/* ++ * ++ * Arp sent timer expired ++ * ++ */ ++static void ++lec_arp_expire_arp(unsigned long data) ++{ ++ struct lec_arp_table *entry; ++ ++ entry = (struct lec_arp_table *)data; ++ ++ del_timer(&entry->timer); ++ ++ DPRINTK("lec_arp_expire_arp\n"); ++ if (entry->status == ESI_ARP_PENDING) { ++ if (entry->no_tries <= entry->priv->max_retry_count) { ++ send_to_lecd(entry->priv, l_arp_xmt, ++ entry->mac_addr, NULL, NULL); ++ entry->no_tries++; ++ } ++ entry->timer.expires = jiffies + (1*HZ); ++ add_timer(&entry->timer); ++ } ++} ++ ++/* ++ * ++ * Unknown/unused vcc expire, remove associated entry ++ * ++ */ ++static void ++lec_arp_expire_vcc(unsigned long data) ++{ ++ struct lec_arp_table *to_remove = (struct lec_arp_table*)data; ++ struct lec_priv *priv = (struct lec_priv *)to_remove->priv; ++ struct lec_arp_table *entry = NULL; ++ ++ del_timer(&to_remove->timer); ++ ++ DPRINTK("LEC_ARP %p %p: lec_arp_expire_vcc vpi:%d vci:%d\n", ++ to_remove, priv, ++ to_remove->vcc?to_remove->recv_vcc->vpi:0, ++ to_remove->vcc?to_remove->recv_vcc->vci:0); ++ DPRINTK("eo:%p nf:%p\n",priv->lec_arp_empty_ones,priv->lec_no_forward); ++ if (to_remove == priv->lec_arp_empty_ones) ++ priv->lec_arp_empty_ones = to_remove->next; ++ else { ++ entry = priv->lec_arp_empty_ones; ++ while (entry && entry->next != to_remove) ++ entry = entry->next; ++ if (entry) ++ entry->next = to_remove->next; ++ } ++ if (!entry) ++ if (to_remove == priv->lec_no_forward) { ++ priv->lec_no_forward = to_remove->next; ++ } else { ++ entry = priv->lec_no_forward; ++ while (entry && entry->next != to_remove) ++ entry = entry->next; ++ if (entry) ++ entry->next = to_remove->next; ++ } ++ lec_arp_clear_vccs(to_remove); ++ kfree(to_remove); ++} ++ ++/* ++ * Expire entries. ++ * 1. Re-set timer ++ * 2. For each entry, delete entries that have aged past the age limit. ++ * 3. For each entry, depending on the status of the entry, perform ++ * the following maintenance. ++ * a. If status is ESI_VC_PENDING or ESI_ARP_PENDING then if the ++ * tick_count is above the max_unknown_frame_time, clear ++ * the tick_count to zero and clear the packets_flooded counter ++ * to zero. This supports the packet rate limit per address ++ * while flooding unknowns. ++ * b. If the status is ESI_FLUSH_PENDING and the tick_count is greater ++ * than or equal to the path_switching_delay, change the status ++ * to ESI_FORWARD_DIRECT. This causes the flush period to end ++ * regardless of the progress of the flush protocol. ++ */ ++static void ++lec_arp_check_expire(unsigned long data) ++{ ++ struct lec_priv *priv = (struct lec_priv *)data; ++ struct lec_arp_table **lec_arp_tables = ++ (struct lec_arp_table **)priv->lec_arp_tables; ++ struct lec_arp_table *entry, *next; ++ unsigned long now; ++ unsigned long time_to_check; ++ int i; ++ ++ del_timer(&priv->lec_arp_timer); ++ ++ DPRINTK("lec_arp_check_expire %p,%d\n",priv, ++ priv->lec_arp_lock_var.counter); ++ DPRINTK("expire: eo:%p nf:%p\n",priv->lec_arp_empty_ones, ++ priv->lec_no_forward); ++ if (!priv->lec_arp_lock_var.counter) { ++ lec_arp_lock(priv); ++ now = jiffies; ++ for(i=0;iflags) & LEC_REMOTE_FLAG && ++ priv->topology_change) ++ time_to_check=priv->forward_delay_time; ++ else ++ time_to_check = priv->aging_time; ++ ++ DPRINTK("About to expire: %lx - %lx > %lx\n", ++ now,entry->last_used, time_to_check); ++ if((now-entry->last_used > time_to_check) && ++ !(entry->flags & LEC_PERMANENT_FLAG)) { ++ /* Remove entry */ ++ DPRINTK("LEC:Entry timed out\n"); ++ next = entry->next; ++ lec_arp_remove(lec_arp_tables, entry); ++ kfree(entry); ++ entry = next; ++ } else { ++ /* Something else */ ++ if ((entry->status == ESI_VC_PENDING || ++ entry->status == ESI_ARP_PENDING) ++ && ++ now-entry->timestamp >= ++ priv->max_unknown_frame_time) { ++ entry->timestamp = jiffies; ++ entry->packets_flooded = 0; ++ } ++ if (entry->status == ESI_FLUSH_PENDING ++ && ++ now-entry->timestamp >= ++ priv->path_switching_delay) { ++ entry->last_used = jiffies; ++ entry->status = ++ ESI_FORWARD_DIRECT; ++ } ++ entry = entry->next; ++ } ++ } ++ } ++ lec_arp_unlock(priv); ++ } ++ priv->lec_arp_timer.expires = jiffies + LEC_ARP_REFRESH_INTERVAL; ++ add_timer(&priv->lec_arp_timer); ++} ++/* ++ * Try to find vcc where mac_address is attached. ++ * ++ */ ++struct atm_vcc* ++lec_arp_resolve(struct lec_priv *priv, unsigned char *mac_to_find) ++{ ++ struct lec_arp_table *entry; ++ ++ if (mac_to_find[0]&0x01) { ++ return priv->mcast_vcc; ++ } ++ entry = lec_arp_find(priv, mac_to_find); ++ ++ if (entry) { ++ if (entry->status == ESI_FORWARD_DIRECT) { ++ /* Connection Ok */ ++ entry->last_used = jiffies; ++ return entry->vcc; ++ } ++ if (entry->status == ESI_UNKNOWN) { ++ del_timer(&entry->timer); ++ goto make_arp_entry; ++ } ++ /* Data direct VC not yet set up, check to see if the unknown ++ frame count is greater than the limit. If the limit has ++ not been reached, allow the caller to send packet to ++ BUS. */ ++ if (entry->status != ESI_FLUSH_PENDING && ++ entry->packets_floodedmaximum_unknown_frame_count) { ++ entry->packets_flooded++; ++ DPRINTK("LEC_ARP: Flooding..\n"); ++ return priv->mcast_vcc; ++ } ++ return NULL; ++ } else { ++ /* No matching entry was found */ ++ entry = make_entry(priv, mac_to_find); ++ DPRINTK("LEC_ARP: Making entry\n"); ++ if (!entry) { ++ return priv->mcast_vcc; ++ } ++ lec_arp_put(priv->lec_arp_tables, entry); ++ make_arp_entry: ++ /* We want arp-request(s) to be sent */ ++ entry->packets_flooded =1; ++ entry->status = ESI_ARP_PENDING; ++ entry->no_tries = 1; ++ entry->last_used = entry->timestamp = jiffies; ++ send_to_lecd(priv, l_arp_xmt, mac_to_find, NULL, NULL); ++ entry->timer.expires = jiffies + (1*HZ); ++ entry->timer.function = lec_arp_expire_arp; ++ add_timer(&entry->timer); ++ return priv->mcast_vcc; ++ } ++} ++ ++int ++lec_addr_delete(struct lec_priv *priv, unsigned char *atm_addr, ++ unsigned long permanent) ++{ ++ struct lec_arp_table *entry, *next; ++ int i; ++ ++ lec_arp_lock(priv); ++ DPRINTK("lec_addr_delete\n"); ++ for(i=0;ilec_arp_tables[i];entry != NULL; entry=next) { ++ next = entry->next; ++ if (!memcmp(atm_addr, entry->atm_addr, ATM_ESA_LEN) ++ && (permanent || ++ !(entry->flags & LEC_PERMANENT_FLAG))) { ++ lec_arp_remove(priv->lec_arp_tables, entry); ++ kfree(entry); ++ } ++ lec_arp_unlock(priv); ++ return 0; ++ } ++ } ++ lec_arp_unlock(priv); ++ return -1; ++} ++ ++/* ++ * Notifies: Response to arp_request (atm_addr != NULL) ++ */ ++void ++lec_arp_update(struct lec_priv *priv, unsigned char *mac_addr, ++ unsigned char *atm_addr, unsigned long remoteflag) ++{ ++ struct lec_arp_table *entry, *tmp; ++ int i; ++ ++ DPRINTK("LEC:lec_arp_update mac:%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x\n", ++ mac_addr[0],mac_addr[1],mac_addr[2],mac_addr[3], ++ mac_addr[4],mac_addr[5]); ++ lec_arp_lock(priv); ++ if (priv->lec_arp_empty_ones) { ++ entry = priv->lec_arp_empty_ones; ++ if (!memcmp(entry->atm_addr, atm_addr, ATM_ESA_LEN)) { ++ priv->lec_arp_empty_ones = entry->next; ++ } else { ++ while(entry->next && memcmp(entry->next->atm_addr, ++ atm_addr, ATM_ESA_LEN)) ++ entry = entry->next; ++ if (entry->next) { ++ tmp = entry; ++ entry = entry->next; ++ tmp->next = entry->next; ++ } else ++ entry = NULL; ++ ++ } ++ if (entry) { ++ del_timer(&entry->timer); ++ tmp = lec_arp_find(priv, mac_addr); ++ if (tmp) { ++ del_timer(&tmp->timer); ++ tmp->status = ESI_FORWARD_DIRECT; ++ memcpy(tmp->atm_addr, atm_addr, ATM_ESA_LEN); ++ tmp->vcc = entry->vcc; ++ tmp->old_push = entry->old_push; ++ tmp->last_used = jiffies; ++ kfree(entry); ++ entry=tmp; ++ } else { ++ entry->status = ESI_FORWARD_DIRECT; ++ memcpy(entry->mac_addr, mac_addr, ETH_ALEN); ++ entry->last_used = jiffies; ++ lec_arp_put(priv->lec_arp_tables, entry); ++ } ++ if (remoteflag) ++ entry->flags|=LEC_REMOTE_FLAG; ++ else ++ entry->flags&=~LEC_REMOTE_FLAG; ++ lec_arp_unlock(priv); ++ DPRINTK("After update\n"); ++ dump_arp_table(priv); ++ return; ++ } ++ } ++ entry = lec_arp_find(priv, mac_addr); ++ if (!entry) { ++ entry = make_entry(priv, mac_addr); ++ entry->status = ESI_UNKNOWN; ++ lec_arp_put(priv->lec_arp_tables, entry); ++ /* Temporary, changes before end of function */ ++ } ++ memcpy(entry->atm_addr, atm_addr, ATM_ESA_LEN); ++ del_timer(&entry->timer); ++ for(i=0;ilec_arp_tables[i];tmp;tmp=tmp->next) { ++ if (entry != tmp && ++ !memcmp(tmp->atm_addr, atm_addr, ++ ATM_ESA_LEN)) { ++ /* Vcc to this host exists */ ++ if (tmp->status > ESI_VC_PENDING) { ++ /* ++ * ESI_FLUSH_PENDING, ++ * ESI_FORWARD_DIRECT ++ */ ++ entry->vcc = tmp->vcc; ++ entry->old_push=tmp->old_push; ++ } ++ entry->status=tmp->status; ++ break; ++ } ++ } ++ } ++ if (remoteflag) ++ entry->flags|=LEC_REMOTE_FLAG; ++ else ++ entry->flags&=~LEC_REMOTE_FLAG; ++ if (entry->status == ESI_ARP_PENDING || ++ entry->status == ESI_UNKNOWN) { ++ entry->status = ESI_VC_PENDING; ++ send_to_lecd(priv, l_svc_setup, NULL, atm_addr, NULL); ++ } ++ DPRINTK("After update2\n"); ++ dump_arp_table(priv); ++ lec_arp_unlock(priv); ++} ++ ++/* ++ * Notifies: Vcc setup ready ++ */ ++void ++lec_vcc_added(struct lec_priv *priv, struct atmlec_ioc *ioc_data, ++ struct atm_vcc *vcc, ++ void (*old_push)(struct atm_vcc *vcc, struct sk_buff *skb)) ++{ ++ struct lec_arp_table *entry; ++ int i, found_entry=0; ++ unsigned char bus_mac[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff,0xff}; ++ ++ lec_arp_lock(priv); ++ if (ioc_data->receive == 2) { ++ /* Vcc for BUS distribute */ ++ DPRINTK("LEC_ARP: Attaching mcast distribute\n"); ++ entry = lec_arp_find(priv, bus_mac); ++ if (!entry) { ++ printk("LEC_ARP: Multicast entry not found!\n"); ++ lec_arp_unlock(priv); ++ return; ++ } ++ memcpy(entry->atm_addr, ioc_data->atm_addr, ATM_ESA_LEN); ++ entry->recv_vcc = vcc; ++ entry->old_recv_push = old_push; ++ lec_arp_unlock(priv); ++ return; ++ } else if (ioc_data->receive == 1) { ++ /* Vcc which we don't want to make default vcc, attach it ++ anyway. */ ++ DPRINTK("LEC_ARP:Attaching data direct, not default :%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x\n", ++ ioc_data->atm_addr[0],ioc_data->atm_addr[1], ++ ioc_data->atm_addr[2],ioc_data->atm_addr[3], ++ ioc_data->atm_addr[4],ioc_data->atm_addr[5], ++ ioc_data->atm_addr[6],ioc_data->atm_addr[7], ++ ioc_data->atm_addr[8],ioc_data->atm_addr[9], ++ ioc_data->atm_addr[10],ioc_data->atm_addr[11], ++ ioc_data->atm_addr[12],ioc_data->atm_addr[13], ++ ioc_data->atm_addr[14],ioc_data->atm_addr[15], ++ ioc_data->atm_addr[16],ioc_data->atm_addr[17], ++ ioc_data->atm_addr[18],ioc_data->atm_addr[19]); ++ entry = make_entry(priv, bus_mac); ++ memcpy(entry->atm_addr, ioc_data->atm_addr, ATM_ESA_LEN); ++ memset(entry->mac_addr, 0, ETH_ALEN); ++ entry->recv_vcc = vcc; ++ entry->old_recv_push = old_push; ++ entry->status = ESI_UNKNOWN; ++ entry->timer.expires = jiffies + priv->vcc_timeout_period; ++ entry->timer.function = lec_arp_expire_vcc; ++ add_timer(&entry->timer); ++ entry->next = priv->lec_no_forward; ++ priv->lec_no_forward = entry; ++ lec_arp_unlock(priv); ++ dump_arp_table(priv); ++ return; ++ } ++ DPRINTK("LEC_ARP:Attaching data direct, default:%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x\n", ++ ioc_data->atm_addr[0],ioc_data->atm_addr[1], ++ ioc_data->atm_addr[2],ioc_data->atm_addr[3], ++ ioc_data->atm_addr[4],ioc_data->atm_addr[5], ++ ioc_data->atm_addr[6],ioc_data->atm_addr[7], ++ ioc_data->atm_addr[8],ioc_data->atm_addr[9], ++ ioc_data->atm_addr[10],ioc_data->atm_addr[11], ++ ioc_data->atm_addr[12],ioc_data->atm_addr[13], ++ ioc_data->atm_addr[14],ioc_data->atm_addr[15], ++ ioc_data->atm_addr[16],ioc_data->atm_addr[17], ++ ioc_data->atm_addr[18],ioc_data->atm_addr[19]); ++ for (i=0;ilec_arp_tables[i];entry;entry=entry->next) { ++ if (memcmp(ioc_data->atm_addr, entry->atm_addr, ++ ATM_ESA_LEN)==0) { ++ DPRINTK("LEC_ARP: Attaching data direct\n"); ++ DPRINTK("Currently -> Vcc: %d, Rvcc:%d\n", ++ entry->vcc?entry->vcc->vci:0, ++ entry->recv_vcc?entry->recv_vcc->vci:0); ++ found_entry=1; ++ del_timer(&entry->timer); ++ if (vcc) { ++ lec_arp_clear_vccs(entry); ++ } ++ entry->vcc = vcc; ++ entry->old_push = old_push; ++ if (entry->status == ESI_VC_PENDING) { ++ if(priv->maximum_unknown_frame_count ++ ==0) ++ entry->status = ++ ESI_FORWARD_DIRECT; ++ else { ++ entry->timestamp = jiffies; ++ entry->status = ++ ESI_FLUSH_PENDING; ++#if 0 ++ send_to_lecd(priv,l_flush_xmt, ++ NULL, ++ entry->atm_addr, ++ NULL); ++#endif ++ } ++ } else { ++ /* They were forming a connection ++ to us, and we to them. Our ++ ATM address is numerically lower ++ than theirs, so we make connection ++ we formed into default VCC (8.1.11). ++ Connection they made gets torn ++ down. This might confuse some ++ clients. Can be changed if ++ someone reports trouble... */ ++ ; ++ } ++ } ++ } ++ } ++ if (found_entry) { ++ lec_arp_unlock(priv); ++ DPRINTK("After vcc was added\n"); ++ dump_arp_table(priv); ++ return; ++ } ++ /* Not found, snatch address from first data packet that arrives from ++ this vcc */ ++ entry = make_entry(priv, bus_mac); ++ entry->vcc = vcc; ++ entry->old_push = old_push; ++ memcpy(entry->atm_addr, ioc_data->atm_addr, ATM_ESA_LEN); ++ memset(entry->mac_addr, 0, ETH_ALEN); ++ entry->status = ESI_UNKNOWN; ++ entry->next = priv->lec_arp_empty_ones; ++ priv->lec_arp_empty_ones = entry; ++ entry->timer.expires = jiffies + priv->vcc_timeout_period; ++ entry->timer.function = lec_arp_expire_vcc; ++ add_timer(&entry->timer); ++ lec_arp_unlock(priv); ++ DPRINTK("After vcc was added\n"); ++ dump_arp_table(priv); ++} ++ ++void ++lec_flush_complete(struct lec_priv *priv, unsigned long tran_id) ++{ ++ struct lec_arp_table *entry; ++ int i; ++ ++ DPRINTK("LEC:lec_flush_complete %lx\n",tran_id); ++ for (i=0;ilec_arp_tables[i];entry;entry=entry->next) { ++ if (entry->flush_tran_id == tran_id && ++ entry->status == ESI_FLUSH_PENDING) { ++ entry->status = ESI_FORWARD_DIRECT; ++ DPRINTK("LEC_ARP: Flushed\n"); ++ } ++ } ++ } ++ dump_arp_table(priv); ++} ++ ++void ++lec_set_flush_tran_id(struct lec_priv *priv, ++ unsigned char *atm_addr, unsigned long tran_id) ++{ ++ struct lec_arp_table *entry; ++ int i; ++ ++ for (i=0;ilec_arp_tables[i];entry;entry=entry->next) ++ if (!memcmp(atm_addr, entry->atm_addr, ATM_ESA_LEN)) { ++ entry->flush_tran_id = tran_id; ++ DPRINTK("Set flush transaction id to %lx for %p\n",tran_id,entry); ++ } ++} ++ ++int ++lec_mcast_make(struct lec_priv *priv, struct atm_vcc *vcc) ++{ ++ unsigned char mac_addr[] = { ++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; ++ struct lec_arp_table *to_add; ++ ++ lec_arp_lock(priv); ++ to_add = make_entry(priv, mac_addr); ++ if (!to_add) ++ return -ENOMEM; ++ to_add->status = ESI_FORWARD_DIRECT; ++ to_add->flags |= LEC_PERMANENT_FLAG; ++ to_add->vcc = vcc; ++ to_add->old_push = vcc->push; ++ vcc->push = lec_push; ++ priv->mcast_vcc = vcc; ++ lec_arp_put(priv->lec_arp_tables, to_add); ++ lec_arp_unlock(priv); ++ return 0; ++} ++ ++void ++lec_vcc_close(struct lec_priv *priv, struct atm_vcc *vcc) ++{ ++ struct lec_arp_table *entry, *next; ++ int i; ++ ++ DPRINTK("LEC_ARP: lec_vcc_close vpi:%d vci:%d\n",vcc->vpi,vcc->vci); ++ dump_arp_table(priv); ++ lec_arp_lock(priv); ++ for(i=0;ilec_arp_tables[i];entry; entry=next) { ++ next = entry->next; ++ if (vcc == entry->vcc) { ++ lec_arp_remove(priv->lec_arp_tables,entry); ++ kfree(entry); ++ if (priv->mcast_vcc == vcc) { ++ priv->mcast_vcc = NULL; ++ } ++ } else if (vcc == entry->recv_vcc) { ++ /* Bus distribution closed */ ++ priv->mcast_vcc = NULL; ++ lec_arp_remove(priv->lec_arp_tables,entry); ++ kfree(entry); ++ lec_arp_unlock(priv); ++ vcc->push(vcc, NULL); ++ return; ++ } ++ } ++ } ++ ++ entry = priv->lec_arp_empty_ones; ++ priv->lec_arp_empty_ones = NULL; ++ while (entry != NULL) { ++ next = entry->next; ++ if (entry->vcc == vcc) { /* leave it out from the list */ ++ lec_arp_clear_vccs(entry); ++ del_timer(&entry->timer); ++ kfree(entry); ++ } ++ else { /* put it back to the list */ ++ entry->next = priv->lec_arp_empty_ones; ++ priv->lec_arp_empty_ones = entry; ++ } ++ entry = next; ++ } ++ ++ entry = priv->lec_no_forward; ++ priv->lec_no_forward = NULL; ++ while (entry != NULL) { ++ next = entry->next; ++ if (entry->recv_vcc == vcc) { ++ lec_arp_clear_vccs(entry); ++ del_timer(&entry->timer); ++ kfree(entry); ++ } ++ else { ++ entry->next = priv->lec_no_forward; ++ priv->lec_no_forward = entry; ++ } ++ entry = next; ++ } ++ ++ lec_arp_unlock(priv); ++ dump_arp_table(priv); ++} ++ ++void ++lec_arp_check_empties(struct lec_priv *priv, ++ struct atm_vcc *vcc, struct sk_buff *skb) ++{ ++ struct lec_arp_table *entry, *prev; ++ struct lecdatahdr_8023 *hdr = (struct lecdatahdr_8023 *)skb->data; ++ unsigned long flags; ++ ++ lec_arp_lock(priv); ++ entry = priv->lec_arp_empty_ones; ++ if (vcc == entry->vcc) { ++ save_flags(flags); ++ cli(); ++ del_timer(&entry->timer); ++ memcpy(entry->mac_addr, hdr->h_source, ETH_ALEN); ++ entry->status = ESI_FORWARD_DIRECT; ++ entry->last_used = jiffies; ++ priv->lec_arp_empty_ones = entry->next; ++ restore_flags(flags); ++ /* We might have got an entry */ ++ if ((prev=lec_arp_find(priv,hdr->h_source))) { ++ lec_arp_remove(priv->lec_arp_tables, prev); ++ kfree(prev); ++ } ++ lec_arp_put(priv->lec_arp_tables, entry); ++ lec_arp_unlock(priv); ++ return; ++ } ++ prev = entry; ++ entry = entry->next; ++ while (entry && entry->vcc != vcc) { ++ prev= entry; ++ entry = entry->next; ++ } ++ if (!entry) { ++ DPRINTK("LEC_ARP: Arp_check_empties: entry not found!\n"); ++ lec_arp_unlock(priv); ++ return; ++ } ++ save_flags(flags); ++ cli(); ++ del_timer(&entry->timer); ++ memcpy(entry->mac_addr, hdr->h_source, ETH_ALEN); ++ entry->status = ESI_FORWARD_DIRECT; ++ entry->last_used = jiffies; ++ prev->next = entry->next; ++ restore_flags(flags); ++ if ((prev = lec_arp_find(priv, hdr->h_source))) { ++ lec_arp_remove(priv->lec_arp_tables,prev); ++ kfree(prev); ++ } ++ lec_arp_put(priv->lec_arp_tables,entry); ++ lec_arp_unlock(priv); ++} ++ +--- /dev/null Tue Jan 1 05:00:00 1980 ++++ work/net/atm/lec.h Fri Mar 13 20:00:07 1998 +@@ -0,0 +1,112 @@ ++/* ++ * ++ * Lan Emulation client header file ++ * ++ * Marko Kiiskila carnil@cs.tut.fi ++ * ++ */ ++ ++#ifndef _LEC_H_ ++#define _LEC_H_ ++ ++#include ++#include ++#include ++ ++#define LEC_HEADER_LEN 16 ++ ++struct lecdatahdr_8023 { ++ unsigned short le_header; ++ unsigned char h_dest[ETH_ALEN]; ++ unsigned char h_source[ETH_ALEN]; ++ unsigned short h_type; ++}; ++ ++struct lecdatahdr_8025 { ++ unsigned short le_header; ++ unsigned char ac_pad; ++ unsigned char fc; ++ unsigned char h_dst[ETH_ALEN]; ++ unsigned char h_source[ETH_ALEN]; ++}; ++ ++/* ++ * ATM LAN Emulation supports both LLC & Dix Ethernet EtherType ++ * frames. ++ * 1. Dix Ethernet EtherType frames encoded by placing EtherType ++ * field in h_type field. Data follows immediatelly after header. ++ * 2. LLC Data frames whose total length, including LLC field and data, ++ * but not padding required to meet the minimum data frame length, ++ * is less than 1536(0x0600) MUST be encoded by placing that length ++ * in the the h_type field. The LLC field follows header immediatelly. ++ * 3. LLC data frames longer than this maximum MUST be encoded by placing ++ * the value 0 in the h_type field. ++ * ++ */ ++ ++/* Hash table size */ ++#define LEC_ARP_TABLE_SIZE 16 ++ ++struct lec_priv { ++ struct enet_statistics stats; ++ unsigned short lecid; /* Lecid of this client */ ++ struct lec_arp_table *lec_arp_empty_ones; ++ /* Used for storing VCC's that don't have a MAC address attached yet */ ++ struct lec_arp_table *lec_arp_tables[LEC_ARP_TABLE_SIZE]; ++ /* Actual LE ARP table */ ++ struct lec_arp_table *lec_no_forward; ++ /* Used for storing VCC's (and forward packets from) which are to ++ age out by not using them to forward packets. ++ This is because to some LE clients there will be 2 VCCs. Only ++ one of them gets used. */ ++ atomic_t lec_arp_lock_var; ++ struct atm_vcc *mcast_vcc; ++ struct atm_vcc *lecd; ++ struct timer_list lec_arp_timer; ++ /* C10 */ ++ unsigned int maximum_unknown_frame_count; ++/* Within the period of time defined by this variable, the client will send ++ no more than C10 frames to BUS for a given unicast destination. (C11) */ ++ unsigned long max_unknown_frame_time; ++/* If no traffic has been sent in this vcc for this period of time, ++ vcc will be torn down (C12)*/ ++ unsigned long vcc_timeout_period; ++/* An LE Client MUST not retry an LE_ARP_REQUEST for a ++ given frame's LAN Destination more than maximum retry count times, ++ after the first LEC_ARP_REQUEST (C13)*/ ++ unsigned short max_retry_count; ++/* Max time the client will maintain an entry in its arp cache in ++ absence of a verification of that relationship (C17)*/ ++ unsigned long aging_time; ++/* Max time the client will maintain an entry in cache when ++ topology change flag is true (C18) */ ++ unsigned long forward_delay_time; ++/* Topology change flag (C19)*/ ++ int topology_change; ++/* Max time the client expects an LE_ARP_REQUEST/LE_ARP_RESPONSE ++ cycle to take (C20)*/ ++ unsigned long arp_response_time; ++/* Time limit ot wait to receive an LE_FLUSH_RESPONSE after the ++ LE_FLUSH_REQUEST has been sent before taking recover action. (C21)*/ ++ unsigned long flush_timeout; ++/* The time since sending a frame to the bus after which the ++ LE Client may assume that the frame has been either discarded or ++ delivered to the recipient (C22) */ ++ unsigned long path_switching_delay; ++ ++ u8 *tlvs; /* LANE2: TLVs are new */ ++ u32 sizeoftlvs; /* The size of the tlv array in bytes */ ++ ++}; ++ ++int lecd_attach(struct atm_vcc *vcc, int arg); ++int lec_vcc_attach(struct atm_vcc *vcc, void *arg); ++int lec_mcast_attach(struct atm_vcc *vcc, int arg); ++struct device **get_dev_lec(void); ++int make_lec(struct atm_vcc *vcc); ++int send_to_lecd(struct lec_priv *priv, ++ atmlec_msg_type type, unsigned char *mac_addr, ++ unsigned char *atm_addr, struct sk_buff *data); ++void lec_push(struct atm_vcc *vcc, struct sk_buff *skb); ++#endif _LEC_H_ ++ +--- /dev/null Tue Jan 1 05:00:00 1980 ++++ work/net/atm/lec_arpc.h Fri Mar 13 20:00:07 1998 +@@ -0,0 +1,112 @@ ++/* ++ * Lec arp cache ++ * Marko Kiiskila carnil@cs.tut.fi ++ * ++ */ ++#ifndef _LEC_ARP_H ++#define _LEC_ARP_H ++#include ++#include ++#include ++#include ++ ++struct lec_arp_table { ++ struct lec_arp_table *next; /* Linked entry list */ ++ unsigned char atm_addr[ATM_ESA_LEN]; /* Atm address */ ++ unsigned char mac_addr[ETH_ALEN]; /* Mac address */ ++ struct atm_vcc *vcc; /* Vcc this entry is attached */ ++ struct atm_vcc *recv_vcc; /* Vcc we receive data from */ ++ void (*old_push)(struct atm_vcc *vcc,struct sk_buff *skb); ++ /* Push that leads to daemon */ ++ void (*old_recv_push)(struct atm_vcc *vcc, struct sk_buff *skb); ++ /* Push that leads to daemon */ ++ void (*old_close)(struct atm_vcc *vcc); ++ /* We want to see when this ++ * vcc gets closed */ ++ unsigned long last_used; /* For expiry */ ++ unsigned long timestamp; /* Used for various timestamping ++ * things: ++ * 1. FLUSH started ++ * (status=ESI_FLUSH_PENDING) ++ * 2. Counting to ++ * max_unknown_frame_time ++ * (status=ESI_ARP_PENDING|| ++ * status=ESI_VC_PENDING) ++ */ ++ unsigned char no_tries; /* No of times arp retry has been ++ tried */ ++ unsigned char status; /* Status of this entry */ ++ unsigned short flags; /* Flags for this entry */ ++ unsigned short packets_flooded; /* Data packets flooded */ ++ unsigned long flush_tran_id; /* Transaction id in flush protocol */ ++ struct timer_list timer; /* Arping timer */ ++ struct lec_priv *priv; /* Pointer back */ ++ ++ u8 *tlvs; /* LANE2: Each MAC address can have TLVs */ ++ u32 sizeoftlvs; /* associated with it. sizeoftlvs tells the */ ++ /* the length of the tlvs array */ ++}; ++ ++struct tlv { /* LANE2: Template tlv struct for accessing */ ++ /* the tlvs in the lec_arp_table->tlvs array*/ ++ u32 type; ++ u8 length; ++ u8 value[255]; ++}; ++ ++/* Status fields */ ++#define ESI_UNKNOWN 0 /* ++ * Next packet sent to this mac address ++ * causes ARP-request to be sent ++ */ ++#define ESI_ARP_PENDING 1 /* ++ * There is no ATM address associated with this ++ * 48-bit address. The LE-ARP protocol is in ++ * progress. ++ */ ++#define ESI_VC_PENDING 2 /* ++ * There is a valid ATM address associated with ++ * this 48-bit address but there is no VC set ++ * up to that ATM address. The signaling ++ * protocol is in process. ++ */ ++#define ESI_FLUSH_PENDING 4 /* ++ * The LEC has been notified of the FLUSH_START ++ * status and it is assumed that the flush ++ * protocol is in process. ++ */ ++#define ESI_FORWARD_DIRECT 5 /* ++ * Either the Path Switching Delay (C22) has ++ * elapsed or the LEC has notified the Mapping ++ * that the flush protocol has completed. In ++ * either case, it is safe to forward packets ++ * to this address via the data direct VC. ++ */ ++ ++/* Flag values */ ++#define LEC_REMOTE_FLAG 0x0001 ++#define LEC_PERMANENT_FLAG 0x0002 ++ ++/* Protos */ ++void lec_arp_init(struct lec_priv *priv); ++int lec_mcast_make(struct lec_priv *priv, struct atm_vcc *vcc); ++void lec_arp_destroy(struct lec_priv *priv); ++void lec_vcc_close(struct lec_priv *priv, struct atm_vcc *vcc); ++ ++struct atm_vcc *lec_arp_resolve(struct lec_priv *priv, ++ unsigned char *mac_to_addr); ++void lec_vcc_added(struct lec_priv *dev, ++ struct atmlec_ioc *ioc_data, struct atm_vcc *vcc, ++ void (*old_push)(struct atm_vcc *vcc, struct sk_buff *skb)); ++void lec_arp_check_empties(struct lec_priv *priv, ++ struct atm_vcc *vcc, struct sk_buff *skb); ++int lec_addr_delete(struct lec_priv *priv, ++ unsigned char *mac_addr, unsigned long permanent); ++void lec_flush_complete(struct lec_priv *priv, unsigned long tran_id); ++void lec_arp_update(struct lec_priv *priv, ++ unsigned char *mac_addr, unsigned char *atm_addr, ++ unsigned long remoteflag); ++void lec_set_flush_tran_id(struct lec_priv *priv, ++ unsigned char *mac_addr, unsigned long tran_id); ++ ++#endif +--- /dev/null Tue Jan 1 05:00:00 1980 ++++ work/net/atm/proc.c Fri Mar 13 23:25:51 1998 +@@ -0,0 +1,607 @@ ++/* net/atm/proc.c - ATM /proc interface */ ++ ++/* Written 1995-1998 by Werner Almesberger, EPFL LRC/ICA */ ++ ++/* ++ * The mechanism used here isn't designed for speed but rather for convenience ++ * of implementation. We only return one entry per read system call, so we can ++ * be reasonably sure not to overrun the page and race conditions may lead to ++ * the addition or omission of some lines but never to any corruption of a ++ * line's internal structure. ++ * ++ * Making the whole thing slightly more efficient is left as an exercise to the ++ * reader. (Suggestions: wrapper which loops to get several entries per system ++ * call; or make --left slightly more clever to avoid O(n^2) characteristics.) ++ * I find it fast enough on my unloaded 266 MHz Pentium 2 :-) ++ */ ++ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include /* for __initfunc */ ++#include ++#include /* for HZ */ ++#include "resources.h" ++#include "common.h" /* atm_proc_init prototype */ ++#include "signaling.h" /* to get sigd - ugly too */ ++ ++#ifdef CONFIG_AREQUIPA ++#include ++void atm_push_arequipa(struct atm_vcc *vcc,struct sk_buff *skb); ++#endif ++ ++#ifdef CONFIG_ATM_CLIP ++#include +#include "ipcommon.h" +extern void clip_push(struct atm_vcc *vcc,struct sk_buff *skb); +#endif + -+#ifdef CONFIG_ATM_LANE ++#if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE) +#include "lec.h" +#include "lec_arpc.h" -+extern struct device *dev_lec[MAX_LEC_ITF]; ++extern struct device **(*ptr_to_get_dev_lec)(void); +#endif + + -+/*extern void eni_proc(int i,char *buf); - not yet @@@ */ ++static ssize_t proc_atm_read(struct file *file,char *buf,size_t count, ++ loff_t *pos); ++ ++ ++static struct file_operations proc_atm_operations = { ++ NULL, /* lseek */ ++ proc_atm_read, /* read */ ++ NULL, /* write */ ++ NULL, /* readdir */ ++ NULL, /* select */ ++ NULL, /* ioctl */ ++ NULL, /* mmap */ ++ NULL, /* no special open code */ ++ NULL, /* no special release */ ++ NULL /* can't fsync */ ++}; ++ ++struct inode_operations proc_atm_inode_operations = { ++ &proc_atm_operations, /* default ATM directory file-ops */ ++ NULL, /* create */ ++ NULL, /* lookup */ ++ NULL, /* link */ ++ NULL, /* unlink */ ++ NULL, /* symlink */ ++ NULL, /* mkdir */ ++ NULL, /* rmdir */ ++ NULL, /* mknod */ ++ NULL, /* rename */ ++ NULL, /* readlink */ ++ NULL, /* follow_link */ ++ NULL, /* readpage */ ++ NULL, /* writepage */ ++ NULL, /* bmap */ ++ NULL, /* truncate */ ++ NULL /* permission */ ++}; ++ ++ ++#define ENTRY(name) static struct proc_dir_entry atm_proc_entry_##name = \ ++ { 0, sizeof(#name)-1, #name, S_IFREG | S_IRUGO, 1, 0, 0, 0, \ ++ &proc_atm_inode_operations, NULL } ++#define REG(name) if (!error) error = proc_register(&atm_proc_root, \ ++ &atm_proc_entry_##name) ++#define INO(name) (atm_proc_entry_##name.low_ino) ++ ++ ++ENTRY(devices); ++ENTRY(pvc); ++ENTRY(svc); ++#ifdef CONFIG_ATM_CLIP ++ENTRY(arp); ++#endif ++#if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE) ++ENTRY(lec); ++#endif ++#ifdef CONFIG_AREQUIPA ++ENTRY(arequipa); ++#endif + + +static int atm_header(ino_t ino,char *buf) +{ -+ switch (ino) { -+ case PROC_ATM_DEVICES: -+ sprintf(buf,"Itf Type ESI/\"MAC\"addr " -+ "AAL(TX,err,RX,err,drop) ...\n"); -+ break; -+ case PROC_ATM_ARP: -+ sprintf(buf,"IPitf TypeEncp Idle IP address " -+ "ATM address\n"); -+ break; -+ case PROC_ATM_SVC: -+ sprintf(buf,"Itf VPI VCI State Remote\n"); -+ break; -+ case PROC_ATM_PVC: -+ sprintf(buf,"Itf VPI VCI AAL RX(PCR,Class) " -+ "TX(PCR,Class)\n"); -+ break; -+#ifdef CONFIG_ATM_LANE -+ case PROC_ATM_LEC: -+ sprintf(buf,"Itf MAC ATM destination Status Flags VPI/VCI Recv VPI/VCI\n"); -+ break; ++ if (ino == INO(devices)) ++ return sprintf(buf,"Itf Type ESI/\"MAC\"addr " ++ "AAL(TX,err,RX,err,drop) ...\n"); ++ if (ino == INO(pvc)) ++ return sprintf(buf,"Itf VPI VCI AAL RX(PCR,Class) " ++ "TX(PCR,Class)\n"); ++ if (ino == INO(svc)) ++ return sprintf(buf,"Itf VPI VCI State Remote\n"); ++#ifdef CONFIG_ATM_CLIP ++ if (ino == INO(arp)) ++ return sprintf(buf,"IPitf TypeEncp Idle IP address " ++ "ATM address\n"); ++#endif ++#if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE) ++ if (ino == INO(lec)) ++ return sprintf(buf,"Itf MAC ATM destination" ++ " Status Flags " ++ "VPI/VCI Recv VPI/VCI\n"); +#endif +#ifdef CONFIG_AREQUIPA -+ case PROC_ATM_AREQUIPA: -+ sprintf(buf,"Itf VPI VCI State Sock# Inode\n"); -+ break; ++ if (ino == INO(arequipa)) ++ return sprintf(buf,"Itf VPI VCI State Sock# Inode\n"); +#endif -+ default: -+ return -EINVAL; -+ } -+ return strlen(buf); ++ return -EINVAL; +} + + @@ -9910,16 +12337,17 @@ + svc = !clip_vcc || clip_vcc->vcc->family == AF_ATMSVC; + off = sprintf(buf,"%-6s%-4s%-4s%5ld ",dev->name,svc ? "SVC" : "PVC", + !clip_vcc || clip_vcc->encap ? "LLC" : "NULL", -+ (jiffies-(clip_vcc ? clip_vcc->last_use : entry->neigh.lastused))/ ++ (jiffies-(clip_vcc ? clip_vcc->last_use : entry->neigh->used))/ + HZ); + ip = (unsigned char *) &entry->ip; + ip_len = sprintf(buf+off,"%d.%d.%d.%d",ip[0],ip[1],ip[2],ip[3]); + off += ip_len; + while (ip_len++ < 16) buf[off++] = ' '; ++off += sprintf(buf+off,"[ref %d]",atomic_read(&entry->neigh->refcnt)); + if (!clip_vcc) + if (entry->expires > jiffies) strcpy(buf+off,"(resolving)\n"); + else sprintf(buf+off,"(expired, ref %d)\n", -+ atomic_read(&entry->neigh.refcnt)); ++ atomic_read(&entry->neigh->refcnt)); + else if (!svc) + sprintf(buf+off,"%d.%d.%d\n",clip_vcc->vcc->dev->number, + clip_vcc->vcc->vpi,clip_vcc->vcc->vci); @@ -9966,12 +12394,12 @@ + +static const char *vcc_state(struct atm_vcc *vcc) +{ -+ if (vcc->flags & ATM_VF_READY) return "CONNECTED"; -+ if (vcc->flags & ATM_VF_RELEASED) return "CLOSING"; -+ if (vcc->flags & ATM_VF_LISTEN) return "LISTEN"; -+ if (vcc->flags & ATM_VF_REGIS) return "INUSE"; -+ if (vcc->flags & ATM_VF_BOUND) return "BOUND"; -+ return "IDLE"; ++ if (vcc->flags & ATM_VF_READY) return "CONNECTED"; ++ if (vcc->flags & ATM_VF_RELEASED) return "CLOSING"; ++ if (vcc->flags & ATM_VF_LISTEN) return "LISTEN"; ++ if (vcc->flags & ATM_VF_REGIS) return "INUSE"; ++ if (vcc->flags & ATM_VF_BOUND) return "BOUND"; ++ return "IDLE"; +} + + @@ -10032,7 +12460,7 @@ +#endif + + -+#ifdef CONFIG_ATM_LANE ++#if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE) + +static char* +lec_arp_get_status_string(unsigned char status) @@ -10096,147 +12524,141 @@ + struct atm_vcc *vcc; + int left; + -+ switch (ino) { -+ case PROC_ATM_DEVICES: -+ left = *pos-1; -+ for (dev = atm_devs; dev && left; dev = dev->next) -+ left--; -+ if (!dev) return 0; -+ dev_info(dev,buf); -+ break; ++ if (ino == INO(devices)) { ++ left = *pos-1; ++ for (dev = atm_devs; dev && left; dev = dev->next) left--; ++ if (!dev) return 0; ++ dev_info(dev,buf); ++ return strlen(buf); ++ } ++ if (ino == INO(pvc)) { ++ left = *pos-1; ++ for (dev = atm_devs; dev; dev = dev->next) ++ for (vcc = dev->vccs; vcc; vcc = vcc->next) ++ if (vcc->family == PF_ATMPVC && ++ vcc->dev && !left--) { ++ pvc_info(vcc,buf); ++ return strlen(buf); ++ } ++ return 0; ++ } ++ if (ino == INO(svc)) { ++ left = *pos-1; ++ for (dev = atm_devs; dev; dev = dev->next) ++ for (vcc = dev->vccs; vcc; vcc = vcc->next) ++ if (vcc->family == PF_ATMSVC && !left--) { ++ svc_info(vcc,buf); ++ return strlen(buf); ++ } ++ return 0; ++ } +#ifdef CONFIG_ATM_CLIP -+ case PROC_ATM_ARP: -+ { -+ struct device *dev; -+ struct atmarp_entry *entry; -+ int count; -+ -+ count = *pos; -+ for (dev = clip_devs; dev; -+ dev = PRIV(dev)->next) -+ for (entry = PRIV(dev)->table; entry; -+ entry = entry->next) { -+ struct clip_vcc *vcc; -+ if (!entry->vccs) { -+ if (--count) continue; -+ atmarp_info(dev,entry, -+ NULL,buf); -+ return strlen(buf); -+ } -+ for (vcc = entry->vccs; vcc; -+ vcc = vcc->next) { -+ if (--count) continue; -+ atmarp_info(dev,entry, -+ vcc,buf); -+ return strlen(buf); -+ } -+ } -+ return 0; ++ if (ino == INO(arp)) { ++ struct device *dev; ++ struct atmarp_entry *entry; ++ int count; ++ ++ count = *pos; ++ for (dev = clip_devs; dev; dev = PRIV(dev)->next) ++ for (entry = PRIV(dev)->table; entry; ++ entry = entry->next) { ++ struct clip_vcc *vcc; ++ ++ if (!entry->vccs) { ++ if (--count) continue; ++ atmarp_info(dev,entry,NULL,buf); ++ return strlen(buf); ++ } ++ for (vcc = entry->vccs; vcc; ++ vcc = vcc->next) { ++ if (--count) continue; ++ atmarp_info(dev,entry,vcc,buf); ++ return strlen(buf); ++ } + } -+ return 0; ++ return 0; ++ } +#endif -+ case PROC_ATM_SVC: -+ left = *pos-1; -+ for (dev = atm_devs; dev; dev = dev->next) -+ for (vcc = dev->vccs; vcc; vcc = vcc->next) -+ if (vcc->family == PF_ATMSVC && -+ !left--) { -+ svc_info(vcc,buf); -+ return strlen(buf); -+ } -+ return 0; -+ case PROC_ATM_PVC: -+ left = *pos-1; -+ for (dev = atm_devs; dev; dev = dev->next) -+ for (vcc = dev->vccs; vcc; vcc = vcc->next) -+ if (vcc->family == PF_ATMPVC && -+ vcc->dev && !left--) { -+ pvc_info(vcc,buf); -+ return strlen(buf); -+ } -+ return 0; +#ifdef CONFIG_AREQUIPA -+ case PROC_ATM_AREQUIPA: -+ left = *pos-1; -+ for (dev = atm_devs; dev; dev = dev->next) -+ for (vcc = dev->vccs; vcc; vcc = vcc->next) -+ if (vcc->push == atm_push_arequipa && -+ !left--) { -+ arequipa_info(vcc,buf); -+ return strlen(buf); -+ } -+ return 0; ++ if (ino == INO(arequipa)) { ++ left = *pos-1; ++ for (dev = atm_devs; dev; dev = dev->next) ++ for (vcc = dev->vccs; vcc; vcc = vcc->next) ++ if (vcc->push == atm_push_arequipa && !left--) { ++ arequipa_info(vcc,buf); ++ return strlen(buf); ++ } ++ return 0; ++ } +#endif -+#ifdef CONFIG_ATM_LANE ++#if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE) ++ if (ino == INO(lec)) { ++ struct lec_priv *priv; ++ struct lec_arp_table *entry; ++ int i, count, d, e; ++ struct device **dev_lec; + -+ case PROC_ATM_LEC: { -+ struct lec_priv *priv; -+ struct lec_arp_table *entry; -+ int i, count, d, e; -+ -+ count = *pos; -+ for(d=0;dpriv)) { -+ for(i=0;ilec_arp_tables[i]; -+ for(;entry;entry=entry->next) { -+ if (!--count) { -+ e=sprintf(buf,"%s ",dev_lec[d]->name); -+ lec_info(entry,buf+e); -+ return strlen(buf); -+ } -+ } -+ } -+ for(entry=priv->lec_arp_empty_ones; -+ entry; entry=entry->next) { -+ if (!--count) { -+ e=sprintf(buf,"%s ", -+ dev_lec[d]->name); -+ lec_info(entry, buf+e); -+ return strlen(buf); -+ } -+ } -+ for(entry=priv->lec_no_forward; -+ entry; entry=entry->next) { -+ if (!--count) { -+ e=sprintf(buf,"%s ", -+ dev_lec[d]->name); -+ lec_info(entry, buf+e); -+ return strlen(buf); -+ } -+ } -+ } -+ } -+ return 0; -+ } -+ -+#endif -+ default: -+ return -EINVAL; ++ if (ptr_to_get_dev_lec == NULL) ++ return 0; /* the lane module is not there yet */ ++ else ++ dev_lec = ptr_to_get_dev_lec(); ++ ++ count = *pos; ++ for(d=0;dpriv)) continue; ++ for(i=0;ilec_arp_tables[i]; ++ for(;entry;entry=entry->next) { ++ if (--count) continue; ++ e=sprintf(buf,"%s ", ++ dev_lec[d]->name); ++ lec_info(entry,buf+e); ++ return strlen(buf); ++ } ++ } ++ for(entry=priv->lec_arp_empty_ones; entry; ++ entry=entry->next) { ++ if (--count) continue; ++ e=sprintf(buf,"%s ",dev_lec[d]->name); ++ lec_info(entry, buf+e); ++ return strlen(buf); ++ } ++ for(entry=priv->lec_no_forward; entry; ++ entry=entry->next) { ++ if (--count) continue; ++ e=sprintf(buf,"%s ",dev_lec[d]->name); ++ lec_info(entry, buf+e); ++ return strlen(buf); ++ } ++ } ++ return 0; + } -+ return strlen(buf); ++#endif ++ return -EINVAL; +} + + +static ssize_t proc_atm_read(struct file *file,char *buf,size_t count, + loff_t *pos) +{ ++ struct atm_dev *dev; + unsigned long page; -+ int length,error; ++ int ino = file->f_dentry->d_inode->i_ino; ++ int length; + + if (count < 0) return -EINVAL; + page = get_free_page(GFP_KERNEL); + if (!page) return -ENOMEM; -+ if (*pos) -+ length = atm_info(file->f_dentry->d_inode->i_ino,pos, -+ (char *) page); -+ else length = atm_header(file->f_dentry->d_inode->i_ino,(char *) page); ++ for (dev = atm_devs; dev; dev = dev->next) ++ if (dev->ops->proc_read && dev->proc_entry->low_ino == ino) ++ break; ++ if (dev) length = dev->ops->proc_read(dev,pos,(char *) page); ++ else if (*pos) length = atm_info(ino,pos,(char *) page); ++ else length = atm_header(ino,(char *) page); + if (length > count) length = -EINVAL; + if (length >= 0) { -+ error = copy_to_user(buf,(char *) page,length); -+ if (error) length = error; ++ if (copy_to_user(buf,(char *) page,length)) length = -EFAULT; + (*pos)++; + } + free_page(page); @@ -10244,60 +12666,68 @@ +} + + -+static struct file_operations proc_atm_operations = { -+ NULL, /* lseek */ -+ proc_atm_read, /* read */ -+ NULL, /* write */ -+ NULL, /* readdir */ -+ NULL, /* select */ -+ NULL, /* ioctl */ -+ NULL, /* mmap */ -+ NULL, /* no special open code */ -+ NULL, /* no special release */ -+ NULL /* can't fsync */ -+}; ++static struct proc_dir_entry atm_proc_root = { 0, 3, "atm", ++ S_IFDIR | S_IRUGO | S_IXUGO, 2, 0, 0, 0, &proc_dir_inode_operations, ++ NULL, NULL, NULL, NULL, NULL }; + -+struct inode_operations proc_atm_inode_operations = { -+ &proc_atm_operations, /* default ATM directory file-ops */ -+ NULL, /* create */ -+ NULL, /* lookup */ -+ NULL, /* link */ -+ NULL, /* unlink */ -+ NULL, /* symlink */ -+ NULL, /* mkdir */ -+ NULL, /* rmdir */ -+ NULL, /* mknod */ -+ NULL, /* rename */ -+ NULL, /* readlink */ -+ NULL, /* follow_link */ -+ NULL, /* readpage */ -+ NULL, /* writepage */ -+ NULL, /* bmap */ -+ NULL, /* truncate */ -+ NULL /* permission */ -+}; ++ ++int atm_proc_dev_register(struct atm_dev *dev) ++{ ++ ENTRY(template); ++ int digits,num; ++ int error; ++ ++ error = -ENOMEM; ++ digits = 0; ++ for (num = dev->number; num; num /= 10) digits++; ++ if (!digits) digits++; ++ dev->proc_entry = kmalloc(sizeof(*dev->proc_entry),GFP_KERNEL); ++ if (!dev->proc_entry) goto fail0; ++ dev->proc_name = kmalloc(strlen(dev->type)+digits+2,GFP_KERNEL); ++ if (!dev->proc_name) goto fail1; ++ *dev->proc_entry = atm_proc_entry_template; ++ dev->proc_entry->name = dev->proc_name; ++ dev->proc_entry->namelen = sprintf(dev->proc_name,"%s:%d",dev->type, ++ dev->number); ++ error = proc_register(&atm_proc_root,dev->proc_entry); ++ if (!error) return 0; ++ kfree(dev->proc_name); ++fail1: ++ kfree(dev->proc_entry); ++fail0: ++ return error; ++} + + -+#define FILE(ino,name,len) &proc_atm, \ -+ (&(struct proc_dir_entry) { ino, len, name, \ -+ S_IFREG | S_IRUGO, 1, 0, 0, 0, &proc_atm_inode_operations, NULL }) -+ -+ -+void atm_proc_init(void) ++void atm_proc_dev_deregister(struct atm_dev *dev) +{ -+ proc_register(FILE(PROC_ATM_DEVICES,"devices",7)); -+ proc_register(FILE(PROC_ATM_ARP,"arp",3)); -+ proc_register(FILE(PROC_ATM_SVC,"svc",3)); -+ proc_register(FILE(PROC_ATM_PVC,"pvc",3)); -+#ifdef CONFIG_ATM_LANE -+ proc_register(FILE(PROC_ATM_LEC,"lec",3)); ++ proc_unregister(&atm_proc_root,dev->proc_entry->low_ino); ++ kfree(dev->proc_entry); ++ kfree(dev->proc_name); ++} ++ ++ ++__initfunc(int atm_proc_init(void)) ++{ ++ int error; ++ ++ error = proc_register(&proc_root,&atm_proc_root); ++ REG(devices); ++ REG(pvc); ++ REG(svc); ++#ifdef CONFIG_ATM_CLIP ++ REG(arp); ++#endif ++#if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE) ++ REG(lec); +#endif +#ifdef CONFIG_AREQUIPA -+ proc_register(FILE(PROC_ATM_AREQUIPA,"arequipa",8)); ++ REG(arequipa); +#endif ++ return error; +} --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/net/atm/protocols.h Wed Nov 19 00:36:59 1997 ++++ work/net/atm/protocols.h Thu Jan 15 22:49:11 1998 @@ -0,0 +1,16 @@ +/* net/atm/protocols.h - ATM protocol handler entry points */ + @@ -10316,11 +12746,11 @@ + +#endif --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/net/atm/pvc.c Wed Nov 19 00:36:59 1997 -@@ -0,0 +1,150 @@ ++++ work/net/atm/pvc.c Mon Feb 9 16:24:56 1998 +@@ -0,0 +1,157 @@ +/* net/atm/pvc.c - ATM PVC sockets */ + -+/* Written 1995-1997 by Werner Almesberger, EPFL LRC */ ++/* Written 1995-1998 by Werner Almesberger, EPFL LRC/ICA */ + + +#include @@ -10460,16 +12890,23 @@ + +__initfunc(void atmpvc_proto_init(struct net_proto *pro)) +{ -+ if (sock_register(&pvc_family_ops) < 0) { -+ printk(KERN_ERR "ATMPVC: can't register"); ++ int error; ++ ++ error = sock_register(&pvc_family_ops); ++ if (error < 0) { ++ printk(KERN_ERR "ATMPVC: can't register (%d)",error); + return; + } +#ifdef CONFIG_AREQUIPA + (void) atm_init_arequipa(); +#endif ++#ifdef CONFIG_PROC_FS ++ error = atm_proc_init(); ++ if (error) printk("atm_proc_init fails with %d\n",error); ++#endif +} --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/net/atm/raw.c Wed Nov 19 00:36:59 1997 ++++ work/net/atm/raw.c Thu Jan 15 22:49:11 1998 @@ -0,0 +1,80 @@ +/* net/atm/raw.c - Raw AAL0 and AAL5 transports */ + @@ -10552,13 +12989,14 @@ + return 0; +} --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/net/atm/resources.c Wed Nov 19 00:36:59 1997 -@@ -0,0 +1,159 @@ ++++ work/net/atm/resources.c Thu Feb 12 17:01:03 1998 +@@ -0,0 +1,174 @@ +/* net/atm/resources.c - Staticly allocated resources */ + -+/* Written 1995-1997 by Werner Almesberger, EPFL LRC */ ++/* Written 1995-1998 by Werner Almesberger, EPFL LRC */ + + ++#include +#include +#include +#include @@ -10566,6 +13004,7 @@ +#include +#include /* for get_fs_long and put_fs_long */ + ++#include "common.h" +#include "resources.h" + + @@ -10588,6 +13027,7 @@ + memset(dev,0,sizeof(*dev)); + dev->type = type; + dev->prev = last_dev; ++ dev->signal = ATM_PHY_SIG_UNKNOWN; + dev->next = NULL; + if (atm_devs) last_dev->next = dev; + else atm_devs = dev; @@ -10635,12 +13075,24 @@ + dev->ops = ops; + dev->flags = flags; + memset((void *) &dev->stats,0,sizeof(struct atm_dev_stats)); -+ return (struct atm_dev *) dev; ++#ifdef CONFIG_PROC_FS ++ if (ops->proc_read) ++ if (atm_proc_dev_register(dev) < 0) { ++ printk(KERN_ERR "atm_dev_register: " ++ "atm_proc_dev_register failed for dev %s\n",type); ++ free_atm_dev(dev); ++ return NULL; ++ } ++#endif ++ return dev; +} + + +void atm_dev_deregister(struct atm_dev *dev) +{ ++#ifdef CONFIG_PROC_FS ++ if (dev->ops->proc_read) atm_proc_dev_deregister(dev); ++#endif + free_atm_dev(dev); +} + @@ -10667,6 +13119,7 @@ + vcc = kmalloc(sizeof(*vcc),GFP_KERNEL); + if (!vcc) return NULL; + memset(vcc,0,sizeof(*vcc)); ++ if (nodev_vccs) nodev_vccs->prev = vcc; + vcc->prev = NULL; + vcc->next = nodev_vccs; + nodev_vccs = vcc; @@ -10684,7 +13137,6 @@ + if (vcc->dev && vcc->dev != hold_dev && !vcc->dev->vccs && + (vcc->dev->flags & ATM_DF_CLOSE)) + shutdown_atm_dev(vcc->dev); -+ +} + + @@ -10714,16 +13166,17 @@ + } +} --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/net/atm/resources.h Wed Nov 19 00:44:34 1997 -@@ -0,0 +1,25 @@ ++++ work/net/atm/resources.h Fri Mar 13 20:00:07 1998 +@@ -0,0 +1,29 @@ +/* net/atm/resources.h - ATM-related resources */ + -+/* Written 1995-1997 by Werner Almesberger, EPFL LRC */ ++/* Written 1995-1998 by Werner Almesberger, EPFL LRC/ICA */ + + +#ifndef NET_ATM_RESOURCES_H +#define NET_ATM_RESOURCES_H + ++#include +#include + + @@ -10731,8 +13184,6 @@ +extern struct atm_vcc *nodev_vccs; /* VCCs not linked to any device */ + + -+/* struct atm_dev *alloc_atm_dev(const char *type); */ -+/* void free_atm_dev(struct atm_dev *dev); */ +struct atm_dev *atm_find_dev(int number); +void shutdown_atm_dev(struct atm_dev *dev); + @@ -10740,13 +13191,18 @@ +void free_atm_vcc(struct atm_vcc *vcc); +void bind_vcc(struct atm_vcc *vcc,struct atm_dev *dev); + ++#ifdef CONFIG_PROC_FS ++int atm_proc_dev_register(struct atm_dev *dev); ++void atm_proc_dev_deregister(struct atm_dev *dev); ++#endif ++ +#endif --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/net/atm/signaling.c Wed Nov 19 04:47:54 1997 -@@ -0,0 +1,255 @@ ++++ work/net/atm/signaling.c Fri Mar 13 20:18:19 1998 +@@ -0,0 +1,253 @@ +/* net/atm/signaling.c - ATM signaling */ + -+/* Written 1995-1997 by Werner Almesberger, EPFL LRC */ ++/* Written 1995-1998 by Werner Almesberger, EPFL LRC/ICA */ + + +#include /* error codes */ @@ -10826,8 +13282,7 @@ + */ + while (!(skb = alloc_skb(sizeof(struct atmsvc_msg),GFP_KERNEL))) + schedule(); -+ skb_put(skb,sizeof(struct atmsvc_msg)); -+ *(struct atmsvc_msg *) skb->data = *msg; ++ *(struct atmsvc_msg *) skb_put(skb,sizeof(struct atmsvc_msg)) = *msg; + sigd_put_skb(skb); +} + @@ -10909,8 +13364,7 @@ + DPRINTK("sigd_enq %d (0x%p)\n",(int) type,vcc); + while (!(skb = alloc_skb(sizeof(struct atmsvc_msg),GFP_KERNEL))) + schedule(); -+ skb_put(skb,sizeof(struct atmsvc_msg)); -+ msg = (struct atmsvc_msg *) skb->data; ++ msg = (struct atmsvc_msg *) skb_put(skb,sizeof(struct atmsvc_msg)); + msg->type = type; + msg->vcc = (unsigned long) vcc; + msg->listen_vcc = (unsigned long) listen_vcc; @@ -11000,7 +13454,7 @@ + return 0; +} --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/net/atm/signaling.h Wed Nov 19 00:44:34 1997 ++++ work/net/atm/signaling.h Fri Mar 13 20:00:07 1998 @@ -0,0 +1,25 @@ +/* net/atm/signaling.h - ATM signaling */ + @@ -11028,11 +13482,11 @@ + +#endif --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/net/atm/svc.c Wed Nov 19 04:40:45 1997 -@@ -0,0 +1,392 @@ ++++ work/net/atm/svc.c Fri Mar 13 21:59:03 1998 +@@ -0,0 +1,384 @@ +/* net/atm/svc.c - ATM SVC sockets */ + -+/* Written 1995-1997 by Werner Almesberger, EPFL LRC */ ++/* Written 1995-1998 by Werner Almesberger, EPFL LRC/ICA */ + + +#include @@ -11095,34 +13549,31 @@ +{ + struct sk_buff *skb; + -+ DPRINTK("svc_disconnect\n"); ++ DPRINTK("svc_disconnect %p\n",vcc); + if (vcc->flags & ATM_VF_REGIS) { + sigd_enq(vcc,as_close,NULL,NULL,NULL); + while (!(vcc->flags & ATM_VF_RELEASED) && sigd) + sleep_on(&vcc->sleep); + } ++ /* beware - socket is still in use by atmsigd until the last ++ as_indicate has been answered */ + while ((skb = skb_dequeue(&vcc->listenq))) { -+ vcc->flags &= ~ATM_VF_RELEASED; + DPRINTK("LISTEN REL\n"); + sigd_enq(NULL,as_reject,vcc,NULL,NULL); /* @@@ should include + the reason */ + dev_kfree_skb(skb,FREE_WRITE); + } -+ vcc->flags &= ~(ATM_VF_REGIS | ATM_VF_RELEASED); /* may retry later */ ++ vcc->flags &= ~(ATM_VF_REGIS | ATM_VF_RELEASED | ATM_VF_CLOSE); ++ /* may retry later */ +} + + +static int svc_release(struct socket *sock,struct socket *peer) +{ -+ struct atm_vcc *vcc; ++ struct atm_vcc *vcc = ATM_SD(sock); + -+ DPRINTK("svc_release\n"); -+ vcc = ATM_SD(sock); ++ DPRINTK("svc_release %p\n",vcc); + if (!vcc) return 0; -+ if ((vcc->flags & (ATM_VF_READY | ATM_VF_RELEASED)) == -+ (ATM_VF_READY | ATM_VF_RELEASED)) -+ vcc->flags &= ~ATM_VF_RELEASED; -+ /* was released by atm_async_release_vcc */ + vcc->flags &= ~ATM_VF_READY; + atm_release_vcc(vcc,0); + svc_disconnect(vcc); @@ -11155,7 +13606,7 @@ + sigd_enq(vcc,as_bind,NULL,NULL,&vcc->local); + while (vcc->reply == WAITING && sigd) sleep_on(&vcc->sleep); + vcc->flags &= ~ATM_VF_REGIS; /* doesn't count */ -+ if (!sigd) return -EUNATCH; /* good code ? @@@ */ ++ if (!sigd) return -EUNATCH; + if (!vcc->reply) vcc->flags |= ATM_VF_BOUND; + return vcc->reply; +} @@ -11165,13 +13616,12 @@ + int sockaddr_len,int flags) +{ + struct sockaddr_atmsvc *addr; -+ struct atm_vcc *vcc; ++ struct atm_vcc *vcc = ATM_SD(sock); + int error; + -+ DPRINTK("svc_connect\n"); ++ DPRINTK("svc_connect %p\n",vcc); + if (sockaddr_len != sizeof(struct sockaddr_atmsvc)) return -EINVAL; + if (sock->state == SS_CONNECTED) return -EISCONN; -+ vcc = ATM_SD(sock); + if (sock->state == SS_CONNECTING) { + if (vcc->reply == WAITING) return -EALREADY; + sock->state = SS_UNCONNECTED; @@ -11197,28 +13647,28 @@ + } + while (vcc->reply == WAITING && sigd) { + interruptible_sleep_on(&vcc->sleep); -+ if (current->signal & ~current->blocked) { ++ if (signal_pending(current)) { + DPRINTK("*ABORT*\n"); + /* + * This is tricky: -+ * Kernel -------close------> Demon -+ * Kernel <-----close(0)----- Demon ++ * Kernel ---close--> Demon ++ * Kernel <--close--- Demon + * or -+ * Kernel -------close------> Demon -+ * Kernel <--close(error)---- Demon ++ * Kernel ---close--> Demon ++ * Kernel <--error--- Demon + * or -+ * Kernel -------close------> Demon -+ * Kernel <------okay-------- Demon -+ * Kernel <-----close(0)----- Demon ++ * Kernel ---close--> Demon ++ * Kernel <--okay---- Demon ++ * Kernel <--close--- Demon + */ -+ vcc->flags &= ~ATM_VF_RELEASED; + sigd_enq(vcc,as_close,NULL,NULL,NULL); + while (vcc->reply == WAITING && sigd) + sleep_on(&vcc->sleep); + if (!vcc->reply) + while (!(vcc->flags & ATM_VF_RELEASED) + && sigd) sleep_on(&vcc->sleep); -+ vcc->flags &= ~(ATM_VF_REGIS | ATM_VF_RELEASED); ++ vcc->flags &= ~(ATM_VF_REGIS | ATM_VF_RELEASED ++ | ATM_VF_CLOSE); + /* we're gone now but may connect later */ + return -EINTR; + } @@ -11245,11 +13695,10 @@ + +static int svc_listen(struct socket *sock,int backlog) +{ -+ struct atm_vcc *vcc; ++ struct atm_vcc *vcc = ATM_SD(sock); + -+ DPRINTK("svc_listen\n"); ++ DPRINTK("svc_listen %p\n",vcc); + /* let server handle listen on unbound sockets */ -+ vcc = ATM_SD(sock); + if (vcc->flags & ATM_VF_SESSION) return -EINVAL; + vcc->reply = WAITING; + sigd_enq(vcc,as_listen,NULL,NULL,&vcc->local); @@ -11265,18 +13714,17 @@ +{ + struct sk_buff *skb; + struct atmsvc_msg *msg; -+ struct atm_vcc *old_vcc,*new_vcc; ++ struct atm_vcc *old_vcc = ATM_SD(sock); ++ struct atm_vcc *new_vcc = ATM_SD(newsock); + int error; + -+ DPRINTK("svc_accept\n"); -+ old_vcc = ATM_SD(sock); -+ new_vcc = ATM_SD(newsock); ++ DPRINTK("svc_accept %p -> %p\n",old_vcc,new_vcc); + while (1) { + while (!(skb = skb_dequeue(&old_vcc->listenq)) && sigd) { ++ if (old_vcc->flags & ATM_VF_RELEASED) break; + if (flags & O_NONBLOCK) return 0; /* not -EAGAIN ? */ + interruptible_sleep_on(&old_vcc->sleep); -+ if (current->signal & ~current->blocked) -+ return -ERESTARTSYS; ++ if (signal_pending(current)) return -ERESTARTSYS; + } + if (!skb) return -EUNATCH; + msg = (struct atmsvc_msg *) skb->data; @@ -11340,14 +13788,12 @@ + char *optval,int optlen) +{ + struct atm_vcc *vcc; -+ int error; + + if (level != __SO_LEVEL(optname) || optname != SO_ATMSAP || + optlen != sizeof(struct atm_sap)) + return atm_setsockopt(sock,level,optname,optval,optlen); + vcc = ATM_SD(sock); -+ error = copy_from_user(&vcc->sap,optval,optlen); -+ if (error) return error; ++ if (copy_from_user(&vcc->sap,optval,optlen)) return -EFAULT; + vcc->flags |= ATM_VF_HASSAP; + return 0; +} @@ -11356,14 +13802,14 @@ +static int svc_getsockopt(struct socket *sock,int level,int optname, + char *optval,int *optlen) +{ -+ int error,len; ++ int len; + + if (level != __SO_LEVEL(optname) || optname != SO_ATMSAP) + return atm_getsockopt(sock,level,optname,optval,optlen); -+ error = get_user(len,optlen); -+ if (error) return error; ++ if (get_user(len,optlen)) return -EFAULT; + if (len != sizeof(struct atm_sap)) return -EINVAL; -+ return copy_to_user(optval,&ATM_SD(sock)->sap,sizeof(struct atm_sap)); ++ return copy_to_user(optval,&ATM_SD(sock)->sap,sizeof(struct atm_sap)) ? ++ -EFAULT : 0; +} + + @@ -11423,7 +13869,7 @@ + } +} --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/net/atm/tunable.h Wed Nov 19 00:36:59 1997 ++++ work/net/atm/tunable.h Thu Jan 15 22:49:11 1998 @@ -0,0 +1,26 @@ +/* net/atm/tunable.h - Tunable parameters of ATM support */ + @@ -11451,8 +13897,8 @@ + quota per PDU */ + +#endif ---- ref/net/core/skbuff.c Fri May 16 01:48:05 1997 -+++ work/net/core/skbuff.c Wed Nov 19 00:36:59 1997 +--- ref/net/core/skbuff.c Tue Jan 13 00:28:25 1998 ++++ work/net/core/skbuff.c Thu Jan 15 22:49:11 1998 @@ -187,6 +187,12 @@ skb->end = bptr + len; skb->len = 0; @@ -11476,7 +13922,7 @@ return n; } -@@ -310,6 +319,9 @@ +@@ -309,6 +318,9 @@ n->stamp=skb->stamp; n->destructor = NULL; n->security=skb->security; diff -ur --new-file old/atm/debug/Makefile new/atm/debug/Makefile --- old/atm/debug/Makefile Tue Sep 23 09:32:31 1997 +++ new/atm/debug/Makefile Thu Mar 12 17:36:19 1998 @@ -1,4 +1,7 @@ -SYSPGMS=aqtest delay ed encopy endump zndump znth +SYSPGMS=aqtest delay svctor # ed encopy endump zndump znth +# Remove the # for more hardware-specific debugging programs. +# I'll need those only if you're fiddling with the guts of drivers. + MAN8= include ../Rules.make diff -ur --new-file old/atm/debug/svctor.c new/atm/debug/svctor.c --- old/atm/debug/svctor.c Thu Jan 1 01:00:00 1970 +++ new/atm/debug/svctor.c Fri Mar 13 18:43:04 1998 @@ -0,0 +1,167 @@ +/* svctor.c - SVC Torture */ + +/* Written 1998 by Werner Almesberger, EPFL ICA */ + +/* + * This program frantically tries to concurrently set up connections to + * itself. Once it has obtained all the connections it was looking for, + * it exits, leaving the system with a lot of things to clean up. + */ + +#define ITF 0 /* interface we use - should be command-line arg */ +#define MAX_PAR 4 /* maximum number of concurrent connect()s */ +#define EXIT_LIM 3 /* exit after establishing that many connections */ +#define MAX_ADDR 10 /* maximum number of local addresses */ +#define SAP "bhli:oui=0x0060D7,id=0x010000ff" +#define QOS "ubr,aal5:tx:max_sdu=100,rx:max_sdu=100" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +void main(void) +{ + static int fd[MAX_PAR]; /* to force initialization */ + struct sockaddr_atmsvc local[MAX_ADDR]; + struct atmif_sioc req; + struct atm_sap sap; + struct atm_qos qos; + int listen_fd; + fd_set rset,wset; + int fds,completed = 0,connects = 0,accepts = 0; + + FD_ZERO(&rset); + FD_ZERO(&wset); + if (text2sap(SAP,&sap,0) < 0) { + fprintf(stderr,"text2sap\n"); + exit(1); + } + if (text2qos(QOS,&qos,0) < 0) { + fprintf(stderr,"text2qos\n"); + exit(1); + } + listen_fd = socket(PF_ATMSVC,SOCK_DGRAM,0); + if (listen_fd < 0) { + perror("socket"); + exit(1); + } + req.number = ITF; + req.arg = local; + req.length = sizeof(local); + if (ioctl(listen_fd,ATM_GETADDR,&req) < 0) { + perror("ioctl"); + exit(1); + } + if (!req.length) { + fprintf(stderr,"No local address\n"); + exit(1); + } + if (setsockopt(listen_fd,SOL_ATM,SO_ATMSAP,&sap,sizeof(sap)) < 0) { + perror("setsockopt SO_ATMSAP"); + exit(1); + } + if (setsockopt(listen_fd,SOL_ATM,SO_ATMQOS,&qos,sizeof(qos)) < 0) { + perror("setsockopt SO_ATMQOS"); + exit(1); + } + if (bind(listen_fd,(struct sockaddr *) local,sizeof(*local)) < 0) { + perror("bind"); + exit(1); + } + if (fcntl(listen_fd,F_SETFL,O_NONBLOCK) < 0) { + perror("fnctl"); + exit(1); + } + if (listen(listen_fd,5) < 0) { + perror("listen"); + exit(1); + } + FD_SET(listen_fd,&rset); + fds = listen_fd+1; + (void) signal(SIGCHLD,SIG_IGN); + while (1) { + static struct timeval no_delay; + fd_set _rset = rset; + fd_set _wset = wset; + int ret,i,empty; + + no_delay.tv_sec = 0; + no_delay.tv_usec = 100000; + ret = select(fds,&_rset,&_wset,NULL,&no_delay); + if (ret < 0) { + perror("select"); + exit(1); + } + if (FD_ISSET(listen_fd,&_rset)) { + pid_t pid; + + pid = fork(); + if (pid < 0) { + perror("fork"); + exit(1); + } + if (!pid) { + if (accept(listen_fd,NULL,NULL) >= 0) exit(0); + perror("accept"); + exit(1); + } + accepts++; + } + empty = -1; + for (i = 0; i < MAX_PAR; i++) + if (!fd[i]) empty = i; + else if (FD_ISSET(fd[i],&_wset)) { + struct sockaddr_atmsvc dummy; + + if (connect(fd[i],(struct sockaddr *) &dummy,sizeof(dummy)) + < 0) { + perror("connect"); + exit(1); + } + FD_CLR(fd[i],&wset); + fd[i] = 0; + empty = i; + if (++completed == EXIT_LIM) { + printf("%d attempted, %d completed, %d accepts\n", + connects,completed,accepts); + exit(0); + } + } + if (empty != -1) { + fd[empty] = socket(PF_ATMSVC,SOCK_DGRAM,0); + if (fd[empty] < 0) { + perror("socket"); + exit(1); + } + if (fcntl(fd[empty],F_SETFL,O_NONBLOCK) < 0) { + perror("fnctl"); + exit(1); + } + if (setsockopt(fd[empty],SOL_ATM,SO_ATMSAP,&sap,sizeof(sap)) < 0) { + perror("setsockopt SO_ATMSAP"); + exit(1); + } + if (setsockopt(fd[empty],SOL_ATM,SO_ATMQOS,&qos,sizeof(qos)) < 0) { + perror("setsockopt SO_ATMQOS"); + exit(1); + } + if (connect(fd[empty],(struct sockaddr *) local,sizeof(*local)) < 0 + && errno != EINPROGRESS) { + perror("connect"); + exit(1); + } + FD_SET(fd[empty],&wset); + if (fds <= fd[empty]) fds = fd[empty]+1; + connects++; + } + } +} diff -ur --new-file old/atm/doc/usage.tex new/atm/doc/usage.tex --- old/atm/doc/usage.tex Tue Nov 18 23:48:20 1997 +++ new/atm/doc/usage.tex Thu Mar 12 17:37:23 1998 @@ -1,7 +1,7 @@ %%def%:= %:\begin{verbatim} -%:Usage instructions - ATM on Linux, release 0.33 (alpha) +%:Usage instructions - ATM on Linux, release 0.34 (alpha) %:--------------------------------------------------------- %: %:\end{verbatim} @@ -38,14 +38,14 @@ \title{ATM on Linux \\ User's guide \\ - Release 0.33 (alpha)} + Release 0.34 (alpha)} \author{Werner Almesberger \\ - {\tt werner.almesberger@lrc.di.epfl.ch} \\ + {\tt Werner.Almesberger@epfl.ch} \\ \\ Institute for computer Communications and Applications (ICA) \\ EPFL, CH-1015 Lausanne, Switzerland} -\date{November 18, 1997} +\date{March 12, 1997} \begin{document} \maketitle @@ -81,9 +81,9 @@ In order to install this package, you need \begin{itemize} \item the package itself - \url{ftp://lrcftp.epfl.ch/pub/linux/atm/dist/atm-0.33.tar.gz} - \item the Linux kernel, version 2.1.65, e.g. from - \url{ftp://ftp.kernel.org/pub/linux/kernel/v2.1/linux-2.1.65.tar.gz} + \url{ftp://lrcftp.epfl.ch/pub/linux/atm/dist/atm-0.34.tar.gz} + \item the Linux kernel, version 2.1.79, e.g. from + \url{ftp://ftp.kernel.org/pub/linux/kernel/v2.1/linux-2.1.79.tar.gz} \item Perl, version 4 or 5 \item if you want memory debugging: MPR version 1.6, e.g. from \url{ftp://sunsite.unc.edu/pub/Linux/devel/lang/c/mpr-1.6.tar.gz} @@ -98,13 +98,13 @@ distribution: \begin{verbatim} -tar xfz atm-0.33.tar.gz +tar xfz atm-0.34.tar.gz \end{verbatim} and the kernel source: \begin{verbatim} -tar xfz linux-2.1.65.tar.gz +tar xfz linux-2.1.79.tar.gz \end{verbatim} Finally, you can extract the ATM-related patches: @@ -137,7 +137,8 @@ \name{les} \item[\path{atm/aqd/}] Arequipa demon: \name{aqpvc}, \name{arequipad} \item[\path{atm/debug/}] Debugging tools: \name{aqtest}, \name{delay}, - \name{ed}, \name{encopy}, \name{endump}, \name{zndump}, and \name{znth} + \name{ed}, \name{encopy}, \name{endump}, \name{svctor}, \name{zndump}, + and \name{znth} \item[\path{atm/lib/}] Libraries for applications and demons \item[\path{atm/doc/}] Documentation in \LaTeX\ and conversion tools \item[\path{atm/man/}] Miscellaneous man pages @@ -149,49 +150,45 @@ \subsection{Kernel configuration} Now, change links (if necessary) and do the usual \raw{make config}, -\raw{make menuconfig}, or \raw{make xconfig}. +\raw{make menuconfig}, or \raw{make xconfig}. First, enable +\begin{verbatim} +Prompt for development and/or incomplete code/drivers + (CONFIG_EXPERIMENTAL) +\end{verbatim} + You should find the following new options: \begin{verbatim} -Asynchronous Transfer Mode (ATM) (CONFIG_ATM) - Enable single-copy (CONFIG_MMU_HACKS) - Extended debugging for single-copy (CONFIG_MMU_HACKS_DEBUG) +Asynchronous Transfer Mode (ATM, EXPERIMENTAL) (CONFIG_ATM) Classical IP over ATM (CONFIG_ATM_CLIP) - Application REQUested IP over ATM (CONFIG_AREQUIPA) - LANE support (CONFIG_ATM_LANE) + LAN Emulation (LANE) support (CONFIG_ATM_LANE) ATM over TCP (CONFIG_ATM_TCP) Efficient Networks ENI155P (CONFIG_ATM_ENI) Enable extended debugging (CONFIG_ATM_ENI_DEBUG) ZeitNet ZN1221/ZN1225 (CONFIG_ATM_ZATM) Enable extended debugging (CONFIG_ATM_ZATM_DEBUG) Enable usec resolution timestamps (CONFIG_ATM_ZATM_EXACT_TS) -Rolfs TI TNETA1570 (CONFIG_ATM_TNETA1570) - Enable extended debugging (CONFIG_ATM_TNETA1570_DEBUG) -IDT 77201 (NICStAR) (CONFIG_ATM_NICSTAR) \end{verbatim} +%after ATM +% Enable single-copy (CONFIG_MMU_HACKS) +% Extended debugging for single-copy (CONFIG_MMU_HACKS_DEBUG) +%after CLIP +% Application REQUested IP over ATM (CONFIG_AREQUIPA) +%after usec +%Rolfs TI TNETA1570 (CONFIG_ATM_TNETA1570) +% Enable extended debugging (CONFIG_ATM_TNETA1570_DEBUG) +%IDT 77201 (NICStAR) (CONFIG_ATM_NICSTAR) + +%The ``MMU hacks'' add single-copy support for raw AAL5 on adapters whose +%driver supports this (currently only the ENI155p). Extended debugging should +%only be enabled when tracing specific problems, because it slows down the +%drivers, and it may introduce new race conditions. -The ``MMU hacks'' add single-copy support for raw AAL5 on adapters whose -driver supports this (currently only the ENI155p). Extended debugging should -only be enabled when tracing specific problems, because it slows down the -drivers, and it may introduce new race conditions. - -The TNETA1570 driver is for a board developed by Rolf Fiedler at TU Chemnitz, -see also \url{ftp://ftp.infotech.tu-chemnitz.de/pub/linux-atm}. +%The TNETA1570 driver is for a board developed by Rolf Fiedler at TU Chemnitz, +%see also \url{ftp://ftp.infotech.tu-chemnitz.de/pub/linux-atm}. -Note that the file \path{drivers/atm/nicstar.h} contains a few configurable -settings for the IDT 77201 driver. - -Support for a simple type of serial consoles is automatically added by the -ATM patch. If you're using \name{LILO}, you can enable it by putting a line -like - -\begin{command} -append="scon=\meta{N}" -\end{command} - -with \meta{N} indicating the serial port (equal to the first number in the -\raw{serial=} line) into \path{/etc/lilo.conf}. Use the \craw{serial} option -of \name{LILO} to make \name{LILO} use the serial console too. +%Note that the file \path{drivers/atm/nicstar.h} contains a few configurable +%settings for the IDT 77201 driver. Then build your kernel and reboot. @@ -400,13 +397,17 @@ Some status information about the ATM subsystem can be obtained through files in \path{/proc/atm}. \path{/proc/atm/arp} contains information specific to -ATMARP, see section \ref{atmarpd}. +Classical IP over ATM, see section \ref{clip}. \path{/proc/atm/devices} lists all active ATM devices. For each device, the interface number, the type label, the end system identifier (ESI), and statistics are shown. The statistics correspond to the ones available via \name{atmdiag}. +Individual ATM devices may register entries of the form +\raw{\meta{type}:\meta{number}} (e.g. \raw{eni:0}) which contain +device-specific information. + \path{/proc/atm/pvc} and \path{/proc/atm/svc} list all PVC and SVC sockets. For both types of sockets, the interface, VPI and VCI numbers are shown. For PVCs, this is followed by the AAL and the traffic class and the selected @@ -667,7 +668,7 @@ If no interface number is specified, \name{ilmid} serves interface 0. \name{atmsigd} should already be running when \name{ilmid} is started, Use the \raw{-b} option to make sure they're properly synchronized (see section -\ref{atmarpd}). +\ref{clip}). The agent supports only the address registration procedures specified in section 5.8 of the ATM Forum's UNI 3.1 specification. These @@ -824,75 +825,14 @@ \section{IP over ATM} \label{ipoveratm} -IP over ATM is supported using two modules:\footnote{The term ``module'' -is used here for a functional software component, not for a loadable kernel -module.} the CLIP module -only supports PVCs and only handles encapsulation according to -RFC1483 \cite{RFC1483}. InARP (defined in RFC1577 \cite{RFC1577}) is not -supported by this mechanism. - -The more advanced ATMARP module includes full support for PVCs and -SVCs (including ATMARP and InARP) as specified in RFC1577, but is still a -bit less reliable than CLIP. - -CLIP will be phased out in the near future. +IP over ATM is supported with Classical IP over ATM (CLIP, defined in +RFC1577 \cite{RFC1577}), and LAN Emulation. \subsection{CLIP} +\label{clip} -Limited IP over ATM for PVCs is supported in this release using the \name{clip} -program. Please be aware that it might not interoperate with other -implementations, because InARP is not supported. - -VCCs are used as IP point to point links, so contrary to what RFC1577 -suggests, VCC selection is a routing decision and not a matter of -address resolution. - -For a better but still immature mechanism see section \ref{atmarpd}. - -First, the VCCs have to be established. Become root on both machines -and run \name{clip} (see \name{clip.8}) on each of them, e.g.: - -\begin{verbatim} -a# clip 0.40 -b# clip 0.40 -\end{verbatim} - -For CBR connections, specify the desired peak cell rate as the second -argument. The default encapsulation is LLC/SNAP, but NULL encapsulation -can be selected with the option \raw{-0} (that's ``zero'', not ``oh''). - -Next, the interfaces have to be configured: - -\begin{command} -\# /sbin/ifconfig atm0 up \meta{src\_addr} dstaddr \meta{dst\_addr} -\end{command} - -e.g. - -\begin{verbatim} -a# /sbin/ifconfig atm0 up 10.0.0.1 dstaddr 10.0.0.2 -b# /sbin/ifconfig atm0 up 10.0.0.2 dstaddr 10.0.0.1 -\end{verbatim} - -Finally, you have to add the routes: - -\begin{verbatim} -a# /sbin/route add 10.0.0.2 -b# /sbin/route add 10.0.0.1 -\end{verbatim} - -Test the connection with ping: - -\begin{verbatim} -a% ping 10.0.0.2 -\end{verbatim} - - -\subsection{ATMARP demon} -\label{atmarpd} - -For ATMARP, a demon process is used to generate and answer ARP queries. +A demon process is used to generate and answer ARP queries. The actual kernel part maintains a small lookup table only containing partial information. @@ -929,7 +869,6 @@ \begin{command} \# atmarp -c \meta{interface\_name}\\ \# ifconfig atm0 \meta{local\_address} \meta{possibly\_more\_options} up\\ -\# route add -net \meta{network\_address} \end{command} e.g. @@ -937,7 +876,6 @@ \begin{verbatim} # atmarp -c atm0 # ifconfig atm0 10.0.0.3 up -# route add -net 10.0.0.0 \end{verbatim} If only PVCs will be used, they can now be created with a command like @@ -952,7 +890,7 @@ When using SVCs, some additional configuration work may be necessary. If the machine is acting as the ATMARP server on that LIS, no additional -configuration is necessary. Otherwise, the ATM address of the ATMARP +configuration is required. Otherwise, the ATM address of the ATMARP server has to be configured. This is done by creating an entry for the network address with the option \raw{arpsrv} set, e.g. @@ -984,37 +922,37 @@ Man pages: \name{bus.8}, \name{lecs.8}, \name{les.8}, and \name{zeppelin.8} -\subsection{Arequipa} - -Arequipa (Application REQUested IP over ATM, \cite{Arequipa}) is an extension -to IP over ATM that adds support for using direct ATM connections (with QOS -parameters, etc.) to carry traffic between INET sockets. On a system that -should use Arequipa connections, the Arequipa demon has to run. - -Man page: \name{arequipad.8} - -The status of Arequipa connections is shown in \path{/proc/atm/arequipa}. - -If \name{atmsigd} is not running, all attempts to use Arequipa fail and -the ioctls set \name{errno} to \name{EUNATCH}. - -The following example illustrates the use of Arequipa with \name{ttcp\_atm}. -A machine ``a'' sends data to a machine ``b'', which is also registered with -that name in the DNS. Furthermore, ``b'' has an entry with the name ``b-atm'' -in the \path{/etc/hosts.atm} file of ``a''. First, execute on ``b'': - -\begin{verbatim} -# arequipad -b -# ttcp_atm -r -s -Q dummy -\end{verbatim} - -then run on ``a'': - -\begin{verbatim} -# arequipad -b -# ttcp_atm -t -s -Q b-atm b -\end{verbatim} - +%\subsection{Arequipa} +% +%Arequipa (Application REQUested IP over ATM, \cite{Arequipa}) is an extension +%to IP over ATM that adds support for using direct ATM connections (with QOS +%parameters, etc.) to carry traffic between INET sockets. On a system that +%should use Arequipa connections, the Arequipa demon has to run. +% +%Man page: \name{arequipad.8} +% +%The status of Arequipa connections is shown in \path{/proc/atm/arequipa}. +% +%If \name{atmsigd} is not running, all attempts to use Arequipa fail and +%the ioctls set \name{errno} to \name{EUNATCH}. +% +%The following example illustrates the use of Arequipa with \name{ttcp\_atm}. +%A machine ``a'' sends data to a machine ``b'', which is also registered with +%that name in the DNS. Furthermore, ``b'' has an entry with the name ``b-atm'' +%in the \path{/etc/hosts.atm} file of ``a''. First, execute on ``b'': +% +%\begin{verbatim} +%# arequipad -b +%# ttcp_atm -r -s -Q dummy +%\end{verbatim} +% +%then run on ``a'': +% +%\begin{verbatim} +%# arequipad -b +%# ttcp_atm -t -s -Q b-atm b +%\end{verbatim} +%} \begin{thebibliography}{8} % \bibitem{I361}ITU-T Recommendation I.361. @@ -1024,9 +962,9 @@ {\em Linux ATM API}, \url{ftp://lrcftp.epfl.ch/pub/linux/atm/api/}, July 1996. - \bibitem{RFC1483}Heinanen, Juha. - {\em Multiprotocol Encapsulation over ATM Adaptation Layer 5}, - RFC1483, July 1993. +% \bibitem{RFC1483}Heinanen, Juha. +% {\em Multiprotocol Encapsulation over ATM Adaptation Layer 5}, +% RFC1483, July 1993. \bibitem{RFC1577}Laubach, Mark. {\em Classical IP and ARP over ATM}, RFC1577, January 1994. @@ -1034,11 +972,12 @@ % Hoffman, Eric; Grossman, Dan; Malis, Andrew. % {\em ATM Signaling Support for IP over ATM}, % IETF, 1995. - \bibitem{Arequipa}Almesberger, Werner; Le Boudec, Jean-Yves; - Oechslin, Philippe. - {\em Application REQuested IP over ATM (AREQUIPA)} (work in progress), - Internet Draft \url{draft-almesberger-arequipa-01.txt}, - June 1996. +% reference RFC +% \bibitem{Arequipa}Almesberger, Werner; Le Boudec, Jean-Yves; +% Oechslin, Philippe. +% {\em Application REQuested IP over ATM (AREQUIPA)} (work in progress), +% Internet Draft \url{draft-almesberger-arequipa-01.txt}, +% June 1996. \end{thebibliography} %%beginskip diff -ur --new-file old/atm/doc/usage.txt new/atm/doc/usage.txt --- old/atm/doc/usage.txt Wed Nov 19 03:57:48 1997 +++ new/atm/doc/usage.txt Fri Mar 13 22:07:11 1998 @@ -1,4 +1,4 @@ -Usage instructions - ATM on Linux, release 0.33 (alpha) +Usage instructions - ATM on Linux, release 0.34 (alpha) --------------------------------------------------------- For updates of ATM on Linux, please check the Web page at @@ -17,9 +17,9 @@ In order to install this package, you need - the package itself - ftp://lrcftp.epfl.ch/pub/linux/atm/dist/atm-0.33.tar.gz - - the Linux kernel, version 2.1.65, e.g. from - ftp://ftp.kernel.org/pub/linux/kernel/v2.1/linux-2.1.65.tar.gz + ftp://lrcftp.epfl.ch/pub/linux/atm/dist/atm-0.34.tar.gz + - the Linux kernel, version 2.1.79, e.g. from + ftp://ftp.kernel.org/pub/linux/kernel/v2.1/linux-2.1.79.tar.gz - Perl, version 4 or 5 - if you want memory debugging: MPR version 1.6, e.g. from ftp://sunsite.unc.edu/pub/Linux/devel/lang/c/mpr-1.6.tar.gz @@ -33,11 +33,11 @@ all the files listed above there. Then extract the ATM on Linux distribution: -tar xfz atm-0.33.tar.gz +tar xfz atm-0.34.tar.gz and the kernel source: -tar xfz linux-2.1.65.tar.gz +tar xfz linux-2.1.79.tar.gz Finally, you can extract the ATM-related patches: @@ -61,8 +61,8 @@ atm/led/ LAN Emulation demon: led atm/lane/ LAN Emulation servers: bus, lecs, les atm/aqd/ Arequipa demon: aqpvc, arequipad - atm/debug/ Debugging tools: aqtest, delay, ed, encopy, endump, zndump, - and znth + atm/debug/ Debugging tools: aqtest, delay, ed, encopy, endump, svctor, + zndump, and znth atm/lib/ Libraries for applications and demons atm/doc/ Documentation in LaTeX and conversion tools atm/man/ Miscellaneous man pages @@ -74,43 +74,22 @@ -------------------- Now, change links (if necessary) and do the usual make config , make -menuconfig , or make xconfig . You should find the following new options: +menuconfig , or make xconfig . First, enable -Asynchronous Transfer Mode (ATM) (CONFIG_ATM) - Enable single-copy (CONFIG_MMU_HACKS) - Extended debugging for single-copy (CONFIG_MMU_HACKS_DEBUG) +Prompt for development and/or incomplete code/drivers + (CONFIG_EXPERIMENTAL) + +You should find the following new options: + +Asynchronous Transfer Mode (ATM, EXPERIMENTAL) (CONFIG_ATM) Classical IP over ATM (CONFIG_ATM_CLIP) - Application REQUested IP over ATM (CONFIG_AREQUIPA) - LANE support (CONFIG_ATM_LANE) + LAN Emulation (LANE) support (CONFIG_ATM_LANE) ATM over TCP (CONFIG_ATM_TCP) Efficient Networks ENI155P (CONFIG_ATM_ENI) Enable extended debugging (CONFIG_ATM_ENI_DEBUG) ZeitNet ZN1221/ZN1225 (CONFIG_ATM_ZATM) Enable extended debugging (CONFIG_ATM_ZATM_DEBUG) Enable usec resolution timestamps (CONFIG_ATM_ZATM_EXACT_TS) -Rolfs TI TNETA1570 (CONFIG_ATM_TNETA1570) - Enable extended debugging (CONFIG_ATM_TNETA1570_DEBUG) -IDT 77201 (NICStAR) (CONFIG_ATM_NICSTAR) - -The "MMU hacks" add single-copy support for raw AAL5 on adapters whose -driver supports this (currently only the ENI155p). Extended debugging -should only be enabled when tracing specific problems, because it slows -down the drivers, and it may introduce new race conditions. - -The TNETA1570 driver is for a board developed by Rolf Fiedler at TU -Chemnitz, see also ftp://ftp.infotech.tu-chemnitz.de/pub/linux-atm . - -Note that the file drivers/atm/nicstar.h contains a few configurable -settings for the IDT 77201 driver. - -Support for a simple type of serial consoles is automatically added by the -ATM patch. If you're using LILO, you can enable it by putting a line like - - append="scon=" - -with indicating the serial port (equal to the first number in the -serial= line) into /etc/lilo.conf. Use the SERIAL option of LILO to make -LILO use the serial console too. Then build your kernel and reboot. @@ -299,14 +278,17 @@ ------------------ Some status information about the ATM subsystem can be obtained through -files in /proc/atm. /proc/atm/arp contains information specific to ATMARP, -see section "ATMARP demon". +files in /proc/atm. /proc/atm/arp contains information specific to +Classical IP over ATM, see section "CLIP". /proc/atm/devices lists all active ATM devices. For each device, the interface number, the type label, the end system identifier (ESI), and statistics are shown. The statistics correspond to the ones available via atmdiag. +Individual ATM devices may register entries of the form : +(e.g. eni:0 ) which contain device-specific information. + /proc/atm/pvc and /proc/atm/svc list all PVC and SVC sockets. For both types of sockets, the interface, VPI and VCI numbers are shown. For PVCs, this is followed by the AAL and the traffic class and the selected PCR for @@ -545,7 +527,7 @@ If no interface number is specified, ilmid serves interface 0. atmsigd should already be running when ilmid is started, Use the -b option to -make sure they're properly synchronized (see section "ATMARP demon"). +make sure they're properly synchronized (see section "CLIP"). The agent supports only the address registration procedures specified in section 5.8 of the ATM Forum's UNI 3.1 specification. These procedures @@ -685,67 +667,15 @@ IP over ATM =========== -IP over ATM is supported using two modules:* the CLIP module only supports -PVCs and only handles encapsulation according to RFC1483 [2]. InARP -(defined in RFC1577 [3]) is not supported by this mechanism. - - * The term "module" is used here for a functional software component, - not for a loadable kernel module. - -The more advanced ATMARP module includes full support for PVCs and SVCs -(including ATMARP and InARP) as specified in RFC1577, but is still a bit -less reliable than CLIP. - -CLIP will be phased out in the near future. +IP over ATM is supported with Classical IP over ATM (CLIP, defined in +RFC1577 [2]), and LAN Emulation. CLIP ---- -Limited IP over ATM for PVCs is supported in this release using the clip -program. Please be aware that it might not interoperate with other -implementations, because InARP is not supported. - -VCCs are used as IP point to point links, so contrary to what RFC1577 -suggests, VCC selection is a routing decision and not a matter of address -resolution. - -For a better but still immature mechanism see section "ATMARP demon". - -First, the VCCs have to be established. Become root on both machines and -run clip (see clip.8) on each of them, e.g.: - -a# clip 0.40 -b# clip 0.40 - -For CBR connections, specify the desired peak cell rate as the second -argument. The default encapsulation is LLC/SNAP, but NULL encapsulation can -be selected with the option -0 (that's "zero", not "oh"). - -Next, the interfaces have to be configured: - - # /sbin/ifconfig atm0 up dstaddr - -e.g. - -a# /sbin/ifconfig atm0 up 10.0.0.1 dstaddr 10.0.0.2 -b# /sbin/ifconfig atm0 up 10.0.0.2 dstaddr 10.0.0.1 - -Finally, you have to add the routes: - -a# /sbin/route add 10.0.0.2 -b# /sbin/route add 10.0.0.1 - -Test the connection with ping: - -a% ping 10.0.0.2 - - -ATMARP demon ------------- - -For ATMARP, a demon process is used to generate and answer ARP queries. The -actual kernel part maintains a small lookup table only containing partial +A demon process is used to generate and answer ARP queries. The actual +kernel part maintains a small lookup table only containing partial information. Man pages: atmarpd.8, atmarp.8 @@ -774,13 +704,12 @@ # atmarp -c # ifconfig atm0 up - # route add -net + e.g. # atmarp -c atm0 # ifconfig atm0 10.0.0.3 up -# route add -net 10.0.0.0 If only PVCs will be used, they can now be created with a command like @@ -792,7 +721,7 @@ When using SVCs, some additional configuration work may be necessary. If the machine is acting as the ATMARP server on that LIS, no additional -configuration is necessary. Otherwise, the ATM address of the ATMARP server +configuration is required. Otherwise, the ATM address of the ATMARP server has to be configured. This is done by creating an entry for the network address with the option arpsrv set, e.g. @@ -820,34 +749,13 @@ Man pages: bus.8, lecs.8, les.8, and zeppelin.8 - -Arequipa --------- - -Arequipa (Application REQUested IP over ATM, [4]) is an extension to IP -over ATM that adds support for using direct ATM connections (with QOS -parameters, etc.) to carry traffic between INET sockets. On a system that -should use Arequipa connections, the Arequipa demon has to run. - -Man page: arequipad.8 - -The status of Arequipa connections is shown in /proc/atm/arequipa. - -If atmsigd is not running, all attempts to use Arequipa fail and the ioctls -set errno to EUNATCH. - -The following example illustrates the use of Arequipa with ttcp_atm. A -machine "a" sends data to a machine "b", which is also registered with that -name in the DNS. Furthermore, "b" has an entry with the name "b-atm" in the -/etc/hosts.atm file of "a". First, execute on "b": - -# arequipad -b -# ttcp_atm -r -s -Q dummy - -then run on "a": - -# arequipad -b -# ttcp_atm -t -s -Q b-atm b +%# arequipad -b +%# ttcp_atm -r -s -Q dummy +% + +%# arequipad -b +%# ttcp_atm -t -s -Q b-atm b +% References @@ -855,10 +763,5 @@ [1] Almesberger, Werner. Linux ATM API, ftp://lrcftp.epfl.ch/pub/linux/atm/api/ , July 1996. - [2] Heinanen, Juha. Multiprotocol Encapsulation over ATM Adaptation - Layer 5, RFC1483, July 1993. - [3] Laubach, Mark. Classical IP and ARP over ATM, RFC1577, January + [2] Laubach, Mark. Classical IP and ARP over ATM, RFC1577, January 1994. - [4] Almesberger, Werner; Le Boudec, Jean-Yves; Oechslin, Philippe. - Application REQuested IP over ATM (AREQUIPA) (work in progress), - Internet Draft draft-almesberger-arequipa-01.txt , June 1996. diff -ur --new-file old/atm/ilmid/ilmid.c new/atm/ilmid/ilmid.c --- old/atm/ilmid/ilmid.c Mon May 19 21:24:55 1997 +++ new/atm/ilmid/ilmid.c Thu Feb 12 16:57:48 1998 @@ -75,7 +75,7 @@ poll_message = create_poll_message(); set_message = create_set_message(); set_oid = &((VarBind *) FIRST_LIST_ELMT(set_message->data->a.set_request->variable_bindings))->name; - esi_oid = get_esi(fd); + esi_oid = get_esi(fd,itf); coldstart_message = create_coldstart_message(); in_message = alloc_t(Message); diff -ur --new-file old/atm/ilmid/io.c new/atm/ilmid/io.c --- old/atm/ilmid/io.c Wed Nov 5 03:18:22 1997 +++ new/atm/ilmid/io.c Thu Feb 26 21:23:21 1998 @@ -25,7 +25,7 @@ #include #include #include -#include +#include #include #include #include @@ -43,14 +43,14 @@ static short atm_itf = -1; /* bad value */ -AsnOid *get_esi(int fd) +AsnOid *get_esi(int fd, int itf) { static AsnOid *name; struct atmif_sioc req; unsigned char esi[ESI_LEN]; int m, n, size; - req.number = 0; + req.number = itf; req.arg = esi; req.length = ESI_LEN; diff -ur --new-file old/atm/ilmid/io.h new/atm/ilmid/io.h --- old/atm/ilmid/io.h Tue Apr 22 04:18:58 1997 +++ new/atm/ilmid/io.h Thu Feb 12 16:57:48 1998 @@ -31,7 +31,7 @@ #define MAX_ILMI_MSG 484 -AsnOid *get_esi(int fd); +AsnOid *get_esi(int fd, int itf); void update_nsap(int itf, AsnOid *netprefix, AsnOid *esi); int wait_for_message(int fd, struct timeval *timeout); int read_message(int fd, Message *message); diff -ur --new-file old/atm/ip/atmarp.c new/atm/ip/atmarp.c --- old/atm/ip/atmarp.c Mon Oct 6 21:58:57 1997 +++ new/atm/ip/atmarp.c Thu Feb 26 20:07:38 1998 @@ -1,6 +1,6 @@ /* atmarp.c - RFC1577 ATMARP control */ -/* Written 1995-1997 by Werner Almesberger, EPFL-LRC */ +/* Written 1995-1998 by Werner Almesberger, EPFL-LRC/ICA */ #include @@ -15,12 +15,11 @@ #include #include #include /* struct ifreq */ +#include #include #include #include -#include /* for MAX_ADDR_LEN for if_arp.h */ -#include /* for ATF_PERM and ATF_PUBL */ #include #include "atm.h" diff -ur --new-file old/atm/lane/atm.c new/atm/lane/atm.c --- old/atm/lane/atm.c Tue Mar 11 11:56:38 1997 +++ new/atm/lane/atm.c Wed Nov 19 13:45:11 1997 @@ -64,6 +64,7 @@ atm_create_socket(unsigned char codepoint, const AtmAddr_t *our_addr) { struct sockaddr_atmsvc server; + struct atm_sap atmsap; struct atm_blli blli; struct atm_qos qos; int fd, ret; @@ -80,7 +81,6 @@ memset(&qos, 0, sizeof(qos)); server.sas_family = AF_ATMSVC; memcpy(server.sas_addr.prv, our_addr, ATM_ESA_LEN); - server.sas_addr.blli = &blli; qos.aal = ATM_AAL5; qos.txtp.traffic_class = ATM_UBR; qos.txtp.max_sdu = 1516; @@ -100,7 +100,16 @@ close(fd); return -1; } - disp_sockaddr(&server); + disp_sockaddr(&server, &blli); + + memset(&atmsap, 0, sizeof(struct atm_sap)); + atmsap.blli[0] = blli; + if (setsockopt(fd,SOL_ATM,SO_ATMSAP,&atmsap,sizeof(atmsap)) < 0) { + dump_error(&atm_unit, "setsockop(SO_ATMSAP)"); + (void) close(fd); + return -1; + } + ret = bind(fd, (struct sockaddr *)&server, len); if (ret <0) { dump_error(&atm_unit, "bind"); @@ -121,6 +130,7 @@ unsigned char codepoint) { struct sockaddr_atmsvc address; + struct atm_sap atmsap; struct atm_blli blli; struct atm_qos qos; int fd, ret; @@ -149,7 +159,7 @@ address.sas_family = AF_ATMSVC; memcpy(address.sas_addr.prv, our_addr, sizeof(AtmAddr_t)); - disp_sockaddr(&address); + disp_sockaddr(&address, &blli); ret = bind(fd, (struct sockaddr *)&address, len); if (ret <0) { @@ -164,7 +174,6 @@ close(fd); return -1; } - address.sas_addr.blli = &blli; memset(&blli, 0, sizeof(blli)); blli.l3_proto = ATM_L3_TR9577; blli.l3.tr9577.ipi = NLPID_IEEE802_1_SNAP; @@ -174,8 +183,16 @@ blli.l3.tr9577.snap[3] = 0x00; blli.l3.tr9577.snap[4] = codepoint; - disp_sockaddr(&address); + disp_sockaddr(&address, &blli); + memset(&atmsap, 0, sizeof(struct atm_sap)); + atmsap.blli[0] = blli; + if (setsockopt(fd,SOL_ATM,SO_ATMSAP,&atmsap,sizeof(atmsap)) < 0) { + dump_error(&atm_unit, "setsockop(SO_ATMSAP)"); + (void) close(fd); + return -1; + } + ret = connect(fd, (struct sockaddr*)&address,sizeof(struct sockaddr_atmsvc)); if (ret < 0) { dump_error(&atm_unit, "connect"); diff -ur --new-file old/atm/lane/atm_lecs.c new/atm/lane/atm_lecs.c --- old/atm/lane/atm_lecs.c Tue Mar 11 11:56:55 1997 +++ new/atm/lane/atm_lecs.c Wed Nov 19 13:45:12 1997 @@ -24,6 +24,7 @@ atm_create_socket(unsigned char codepoint, const unsigned char *our_addr) { struct sockaddr_atmsvc server; + struct atm_sap atmsap; struct atm_blli blli; struct atm_qos qos; int fd, ret; @@ -41,7 +42,6 @@ server.sas_family = AF_ATMSVC; if (our_addr) memcpy(server.sas_addr.prv, our_addr, ATM_ESA_LEN); - server.sas_addr.blli = &blli; qos.aal = ATM_AAL5; qos.txtp.traffic_class = ATM_UBR; qos.txtp.max_sdu = 1516; @@ -61,6 +61,15 @@ close(fd); return -1; } + + memset(&atmsap, 0, sizeof(struct atm_sap)); + atmsap.blli[0] = blli; + if (setsockopt(fd,SOL_ATM,SO_ATMSAP,&atmsap,sizeof(atmsap)) < 0) { + perror("setsockop(SO_ATMSAP)"); + (void) close(fd); + return -1; + } + ret = bind(fd, (struct sockaddr *)&server, len); if (ret <0) { perror("bind(fd, ...)"); diff -ur --new-file old/atm/lane/connect.c new/atm/lane/connect.c --- old/atm/lane/connect.c Sun Aug 18 22:45:00 1996 +++ new/atm/lane/connect.c Sun Jan 18 12:14:14 1998 @@ -45,21 +45,25 @@ static int timer_handler(const Event_t *event, void *funcdata); static void conn_main(void); -static int join(const Conn_t *conn); -static int join_ok(const Conn_t *conn); -static int join_bad(const Conn_t *conn); -static int join_close(const Conn_t *conn); -static int join_expire(const Conn_t *conn); -static int idle_bad(const Conn_t *conn); -static int topology_request(const Conn_t *conn); +/* + * as in connect_bus.c had to remove const qualifiers since + * not every function honored it + */ +static int join(Conn_t *conn); +static int join_ok(Conn_t *conn); +static int join_bad(Conn_t *conn); +static int join_close(Conn_t *conn); +static int join_expire(Conn_t *conn); +static int idle_bad(Conn_t *conn); +static int topology_request(Conn_t *conn); -static int register_req(const Conn_t *conn); -static int unregister_req(const Conn_t *conn); +static int register_req(Conn_t *conn); +static int unregister_req(Conn_t *conn); -static int arp_find(const Conn_t *conn); -static int arp_forward_response(const Conn_t *conn); +static int arp_find(Conn_t *conn); +static int arp_forward_response(Conn_t *conn); -static int forward_flush_response(const Conn_t *conn); +static int forward_flush_response(Conn_t *conn); static int is_multicast(const LaneDestination_t *to_detect); static int proper_request(void); @@ -558,7 +562,7 @@ * State transition functions */ static int -join(const Conn_t *conn) +join(Conn_t *conn) { int timeout; int rfd; @@ -579,9 +583,9 @@ } static int -join_ok(const Conn_t *conn) +join_ok(Conn_t *conn) { - Reg_t *rtmp; + Reg_t *rtmp = NULL; /* silence gcc 2.7.2.1 */ Lecdb_t *ltmp; const char *elanname; @@ -675,7 +679,7 @@ } static int -join_bad(const Conn_t *conn) +join_bad(Conn_t *conn) { Debug_unit(&conn_unit, "Join_bad called"); dump_conn(conn); @@ -688,7 +692,7 @@ } static int -idle_bad(const Conn_t *conn) +idle_bad(Conn_t *conn) { Debug_unit(&conn_unit, "Idle bad called"); dump_conn(conn); @@ -697,7 +701,7 @@ } static int -join_close(const Conn_t *conn) +join_close(Conn_t *conn) { Lecdb_t *tmp; @@ -735,7 +739,7 @@ } static int -join_expire(const Conn_t *conn) +join_expire(Conn_t *conn) { Debug_unit(&conn_unit, "Join_expire called"); @@ -746,7 +750,7 @@ } static int -register_req(const Conn_t *conn) +register_req(Conn_t *conn) { Reg_t *tmp; Lecdb_t *ltmp; @@ -794,7 +798,7 @@ } static int -unregister_req(const Conn_t *conn) +unregister_req(Conn_t *conn) { Reg_t *tmp; Lecdb_t *ltmp; @@ -838,7 +842,7 @@ } static int -arp_find(const Conn_t *conn) +arp_find(Conn_t *conn) { Reg_t *tmp; Lecdb_t *ltmp; @@ -882,7 +886,7 @@ } static int -arp_forward_response(const Conn_t *conn) +arp_forward_response(Conn_t *conn) { int a; Conn_t *tmp; @@ -902,7 +906,7 @@ } static int -forward_flush_response(const Conn_t *conn) +forward_flush_response(Conn_t *conn) { int a; @@ -919,7 +923,7 @@ } static int -topology_request(const Conn_t *conn) +topology_request(Conn_t *conn) { int a; diff -ur --new-file old/atm/lane/connect.h new/atm/lane/connect.h --- old/atm/lane/connect.h Thu Aug 8 23:22:42 1996 +++ new/atm/lane/connect.h Sun Jan 18 12:14:23 1998 @@ -67,7 +67,7 @@ EventType_t event; unsigned short opcode; const char *descript; - int (*func)(const Conn_t *conn); + int (*func)(Conn_t *conn); /* removed const, hessu@cs.tut.fi */ ConnState_t nextstate; } State_t; diff -ur --new-file old/atm/lane/connect_bus.c new/atm/lane/connect_bus.c --- old/atm/lane/connect_bus.c Thu Aug 8 23:21:37 1996 +++ new/atm/lane/connect_bus.c Sun Jan 18 12:14:33 1998 @@ -39,11 +39,14 @@ static int data_handler(const Event_t *event, void *funcdata); static void conn_main(void); -static int join(const Conn_t *conn); -static int idle_bad(const Conn_t *conn); +/* Had to remove const qualifiers since not every + * function honored it. hessu@cs.tut.fi + */ +static int join(Conn_t *conn); +static int idle_bad(Conn_t *conn); -static int data_forward(const Conn_t *conn); -static int join_close(const Conn_t *conn); +static int data_forward(Conn_t *conn); +static int join_close(Conn_t *conn); /* Data */ #define BUFSIZE 20000 @@ -365,7 +368,7 @@ * State transition functions */ static int -join(const Conn_t *conn) +join(Conn_t *conn) { int rfd; @@ -386,7 +389,7 @@ } static int -idle_bad(const Conn_t *conn) +idle_bad(Conn_t *conn) { Debug_unit(&conn_unit,"Idle_bad called"); dump_conn(conn); @@ -395,7 +398,7 @@ } static int -data_forward(const Conn_t *conn) +data_forward(Conn_t *conn) { Conn_t *tmp; char packet_string[1024]; @@ -429,7 +432,7 @@ } static int -join_close(const Conn_t *conn) +join_close(Conn_t *conn) { Debug_unit(&conn_unit,"Join_close called"); diff -ur --new-file old/atm/lane/dump.c new/atm/lane/dump.c --- old/atm/lane/dump.c Tue Oct 1 18:26:38 1996 +++ new/atm/lane/dump.c Wed Nov 19 13:45:12 1997 @@ -425,7 +425,7 @@ } void -disp_sockaddr(struct sockaddr_atmsvc *addr) +disp_sockaddr(struct sockaddr_atmsvc *addr, struct atm_blli *blli) { int i; dump_printf(EL_DEBUG,"Socket_address"); @@ -433,18 +433,12 @@ for(i=0;i<20;i++) { dump_printf(EL_CONT,"%2.2x ",addr->sas_addr.prv[i]); } - if (!addr->sas_addr.blli) { - dump_printf(EL_CONT,"No blli information\n"); - fflush(stdout); - } else { - dump_printf(EL_CONT,"\nBlli:\n\t"); - dump_printf(EL_CONT,"l2_proto:%d\n\t",addr->sas_addr.blli->l2_proto); - dump_printf(EL_CONT,"l3_proto:%d\n\t\t",addr->sas_addr.blli->l3_proto); - dump_printf(EL_CONT,"ipi:%x\tsnap:",addr->sas_addr.blli->l3.tr9577.ipi); - for(i=0;i<5;i++) { - dump_printf(EL_CONT,"%2.2x ",addr->sas_addr.blli->l3.tr9577.snap[i]); - } - dump_printf(EL_CONT,"\n"); + dump_printf(EL_CONT,"\nBlli:\n\t"); + dump_printf(EL_CONT,"l2_proto:%d\n\t",blli->l2_proto); + dump_printf(EL_CONT,"l3_proto:%d\n\t\t",blli->l3_proto); + dump_printf(EL_CONT,"ipi:%x\tsnap:",blli->l3.tr9577.ipi); + for(i=0;i<5;i++) { + dump_printf(EL_CONT,"%2.2x ",blli->l3.tr9577.snap[i]); } + dump_printf(EL_CONT,"\n"); } - diff -ur --new-file old/atm/lane/dump.h new/atm/lane/dump.h --- old/atm/lane/dump.h Tue Oct 1 18:27:55 1996 +++ new/atm/lane/dump.h Wed Nov 19 13:45:13 1997 @@ -38,7 +38,7 @@ void dump_addr(const LaneDestination_t *addr); void dump_atmaddr(const AtmAddr_t *addr); void dump_control(const LaneControl_t *c); -void disp_sockaddr(struct sockaddr_atmsvc *addr); +void disp_sockaddr(struct sockaddr_atmsvc *addr, struct atm_blli *blli); /* Global data */ extern const Unit_t dump_unit; diff -ur --new-file old/atm/lane/lane.c new/atm/lane/lane.c --- old/atm/lane/lane.c Thu Sep 12 02:13:39 1996 +++ new/atm/lane/lane.c Sun Jan 18 12:14:42 1998 @@ -171,7 +171,7 @@ static void parse_args(int argc, char **argv) { - int i; + int i = 0; const Unit_t *unit, **units; progname = argv[0]; diff -ur --new-file old/atm/lane/lecs_load.c new/atm/lane/lecs_load.c --- old/atm/lane/lecs_load.c Thu Sep 12 02:23:26 1996 +++ new/atm/lane/lecs_load.c Sun Jan 18 12:14:53 1998 @@ -19,7 +19,7 @@ int load_db(const char *filename) { - int ret; + int ret = 0; /* silence gcc 2.7.2.1 */ int readnew=1; Elan_t *elan =NULL; char message[300]; diff -ur --new-file old/atm/lane/load.c new/atm/lane/load.c --- old/atm/lane/load.c Thu Sep 12 02:02:50 1996 +++ new/atm/lane/load.c Sun Jan 18 12:15:02 1998 @@ -451,7 +451,7 @@ { const Unit_t *curr_unit = NULL; - int ret; + int ret = 0; /* to silence gcc 2.7.2.1 */ char *varname; InitPvc_t *pvc; LaneDestList_t *ltmp; diff -ur --new-file old/atm/led/address.c new/atm/led/address.c --- old/atm/led/address.c Tue Apr 22 21:53:11 1997 +++ new/atm/led/address.c Wed Nov 19 12:59:16 1997 @@ -49,7 +49,7 @@ /* Digital prototypes */ #include "g_types.h" -#include "atm.h" +#include "lane_atm.h" #include "af_lane.h" #include "addr_reg.h" #include "codes.h" diff -ur --new-file old/atm/led/af_lane.h new/atm/led/af_lane.h --- old/atm/led/af_lane.h Wed Apr 16 14:17:27 1997 +++ new/atm/led/af_lane.h Wed Nov 19 12:59:15 1997 @@ -53,7 +53,7 @@ #ifndef _AF_LANE_H_ #define _AF_LANE_H_ -#include "atm.h" +#include "lane_atm.h" #define LE_CTRL_MARKER 0xff00 #define LE_CTRL_PROTOCOL 1 diff -ur --new-file old/atm/led/atm.h new/atm/led/atm.h --- old/atm/led/atm.h Wed Apr 16 14:17:27 1997 +++ new/atm/led/atm.h Thu Jan 1 01:00:00 1970 @@ -1,190 +0,0 @@ -/************************************************************************* - (c) Copyright. Digital Equipment Corporation, 1995. All Rights - Reserved. - - Permission is hereby granted to use, copy, modify, or enhance this - software freely, as long as the foregoing copyright of Digital Equipment - Corporation and this notice are retained on the software. This - software may not be distributed or sublicensed for a fee. Digital - makes this software available "AS IS" and without warranties of any - kind. - *************************************************************************/ -/* - * Marko Kiiskila carnil@cs.tut.fi - * - * Tampere University of Technology - Telecommunications Laboratory - * - * Permission to use, copy, modify and distribute this - * software and its documentation is hereby granted, - * provided that both the copyright notice and this - * permission notice appear in all copies of the software, - * derivative works or modified versions, and any portions - * thereof, that both notices appear in supporting - * documentation, and that the use of this software is - * acknowledged in any publications resulting from using - * the software. - * - * TUT ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" - * CONDITION AND DISCLAIMS ANY LIABILITY OF ANY KIND FOR - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS - * SOFTWARE. - * - */ - -/* -* Module Name: -* atm.h -* -* Abstract: -* This module defines ATM specific types and constants. -* -* Authors: -* TLR - Theodore L. Ross -* -* Modification History: -* Date Name Description -* 16-Sep-94 TLR Created. -* 31-Oct-94 DMW Use INT8 instead of UCHAR, add definition for PREFIX. -* Change definition for ADDR_ATM to use basic types and -* to not have selector be an array. -* 10-Jan-95 TLR Added address copy and compare methods. -* 08-Sep-95 TLR Updated QOS definitions and removed buggy atm_is_greater. -* -* Description: -* Only ATM specific types should be defined here. ---*/ -#ifndef ATM_H -#define ATM_H - -/* General address related definitions. */ - -typedef UINT8 ADDR_48[6]; /* MAC Address. */ -typedef UINT8 ESI[6]; /* End System Identifier */ -typedef UINT8 PREFIX[13]; /* Network Prefix. */ - -/* Type for ATM Address. */ - -typedef struct - { - PREFIX prefix; /* Network Prefix set by the switch. */ - ESI esi; /* ESI or MAC Addr */ - UINT8 sel; /* Selector */ - } ADDR_ATM; - -typedef union - { - struct - { - UINT8 cpcs_uu; - UINT8 clp; - } aal5_data; - } AAL_DATA; - -#define ESI_COPY(from, to) \ - { \ - (to)[0] = (from)[0]; \ - (to)[1] = (from)[1]; \ - (to)[2] = (from)[2]; \ - (to)[3] = (from)[3]; \ - (to)[4] = (from)[4]; \ - (to)[5] = (from)[5]; \ - } - -#define ESI_IS_BCAST(esi) (((esi)[0] == 0xff) && \ - ((esi)[1] == 0xff) && \ - ((esi)[2] == 0xff) && \ - ((esi)[3] == 0xff) && \ - ((esi)[4] == 0xff) && \ - ((esi)[5] == 0xff)) - -#define ATM_COPY(from, to) \ - { \ - (to).prefix[0] = (from).prefix[0]; \ - (to).prefix[1] = (from).prefix[1]; \ - (to).prefix[2] = (from).prefix[2]; \ - (to).prefix[3] = (from).prefix[3]; \ - (to).prefix[4] = (from).prefix[4]; \ - (to).prefix[5] = (from).prefix[5]; \ - (to).prefix[6] = (from).prefix[6]; \ - (to).prefix[7] = (from).prefix[7]; \ - (to).prefix[8] = (from).prefix[8]; \ - (to).prefix[9] = (from).prefix[9]; \ - (to).prefix[10] = (from).prefix[10]; \ - (to).prefix[11] = (from).prefix[11]; \ - (to).prefix[12] = (from).prefix[12]; \ - (to).esi[0] = (from).esi[0]; \ - (to).esi[1] = (from).esi[1]; \ - (to).esi[2] = (from).esi[2]; \ - (to).esi[3] = (from).esi[3]; \ - (to).esi[4] = (from).esi[4]; \ - (to).esi[5] = (from).esi[5]; \ - (to).sel = (from).sel; \ - } - -#define ATM_COPY_NULL(to) \ - { \ - (to).prefix[0] = 0; \ - (to).prefix[1] = 0; \ - (to).prefix[2] = 0; \ - (to).prefix[3] = 0; \ - (to).prefix[4] = 0; \ - (to).prefix[5] = 0; \ - (to).prefix[6] = 0; \ - (to).prefix[7] = 0; \ - (to).prefix[8] = 0; \ - (to).prefix[9] = 0; \ - (to).prefix[10] = 0; \ - (to).prefix[11] = 0; \ - (to).prefix[12] = 0; \ - (to).esi[0] = 0; \ - (to).esi[1] = 0; \ - (to).esi[2] = 0; \ - (to).esi[3] = 0; \ - (to).esi[4] = 0; \ - (to).esi[5] = 0; \ - (to).sel = 0; \ - } - -#define ATM_EQUAL(a1, a2) (((a1).sel == (a2).sel) && \ - ((a1).esi[5] == (a2).esi[5]) && \ - ((a1).esi[4] == (a2).esi[4]) && \ - ((a1).esi[3] == (a2).esi[3]) && \ - ((a1).esi[2] == (a2).esi[2]) && \ - ((a1).esi[1] == (a2).esi[1]) && \ - ((a1).esi[0] == (a2).esi[0]) && \ - ((a1).prefix[12] == (a2).prefix[12]) && \ - ((a1).prefix[11] == (a2).prefix[11]) && \ - ((a1).prefix[10] == (a2).prefix[10]) && \ - ((a1).prefix[9] == (a2).prefix[9]) && \ - ((a1).prefix[8] == (a2).prefix[8]) && \ - ((a1).prefix[7] == (a2).prefix[7]) && \ - ((a1).prefix[6] == (a2).prefix[6]) && \ - ((a1).prefix[5] == (a2).prefix[5]) && \ - ((a1).prefix[4] == (a2).prefix[4]) && \ - ((a1).prefix[3] == (a2).prefix[3]) && \ - ((a1).prefix[2] == (a2).prefix[2]) && \ - ((a1).prefix[1] == (a2).prefix[1]) && \ - ((a1).prefix[0] == (a2).prefix[0])) - -#define ATM_EQUAL_NULL(a1) (((a1).sel == 0) && \ - ((a1).esi[5] == 0) && \ - ((a1).esi[4] == 0) && \ - ((a1).esi[3] == 0) && \ - ((a1).esi[2] == 0) && \ - ((a1).esi[1] == 0) && \ - ((a1).esi[0] == 0) && \ - ((a1).prefix[12] == 0) && \ - ((a1).prefix[11] == 0) && \ - ((a1).prefix[10] == 0) && \ - ((a1).prefix[9] == 0) && \ - ((a1).prefix[8] == 0) && \ - ((a1).prefix[7] == 0) && \ - ((a1).prefix[6] == 0) && \ - ((a1).prefix[5] == 0) && \ - ((a1).prefix[4] == 0) && \ - ((a1).prefix[3] == 0) && \ - ((a1).prefix[2] == 0) && \ - ((a1).prefix[1] == 0) && \ - ((a1).prefix[0] == 0)) - -#endif /* ATM_H */ diff -ur --new-file old/atm/led/cm_sap.h new/atm/led/cm_sap.h --- old/atm/led/cm_sap.h Wed Apr 16 14:17:27 1997 +++ new/atm/led/cm_sap.h Wed Nov 19 12:59:15 1997 @@ -60,7 +60,7 @@ * Dependencies: * types.h - Generally used type definitions. * codes.h - Completion codes. -* atm.h - ATM specific definitions and types. +* lane_atm.h - ATM specific definitions and types. * svc_info.h - SVC Information Block Definitions. * * Description: @@ -117,13 +117,13 @@ * * The connection manager is not specific to any particular ATM Adaptation * Layer (AAL). An AAL_Data field is passed along with each transmit and -* receive packet. Refer to the definition of AAL_DATA in the "atm.h" +* receive packet. Refer to the definition of AAL_DATA in the "lane_atm.h" * header file. * */ #ifndef CM_SAP_H #define CM_SAP_H -#include "atm.h" +#include "lane_atm.h" #include "svc_info.h" #include "system.h" /************************************************************************* diff -ur --new-file old/atm/led/conn.c new/atm/led/conn.c --- old/atm/led/conn.c Tue Oct 7 08:57:52 1997 +++ new/atm/led/conn.c Thu Mar 5 22:07:22 1998 @@ -54,7 +54,7 @@ #include "g_types.h" #include "cm_sap.h" #include "lec.h" -#include "atm.h" +#include "lane_atm.h" #include "atmsap.h" #include "cm.h" #include "g_event.h" @@ -284,6 +284,7 @@ int ret; struct sockaddr_atmsvc us; struct atm_blli blli; + struct atm_sap atmsap; EVENT(EM_EVENT,("Outgoing call setup\n")); @@ -314,7 +315,7 @@ } /* Create socket */ - s = socket(PF_ATMSVC, SOCK_DGRAM, ATM_AAL5); + s = socket(PF_ATMSVC, SOCK_DGRAM, 0); if (s<0) { EVENT(EM_NERR,("socket creation failure:%s\n",strerror(errno))); if (is_data_direct(p_conn_info)) { @@ -337,8 +338,6 @@ return STATUS_K_ATM_RESOURCES; } - /* Create local binding point */ - us.sas_addr.blli = &blli; /* Copy blli information */ memcpy(&blli, &(p_conn_info->blli), sizeof(struct atm_blli)); /* Set traffic parameters */ @@ -357,7 +356,16 @@ us.sas_family = p_conn_info->addr.sas_family; if (EMASK & EM_DEBUG) - disp_sockaddr(&us); + disp_sockaddr(p_conn_info); + + /* new since 0.33-pre-x, SO_ATMSAP */ + memset(&atmsap, 0, sizeof(struct atm_sap)); + atmsap.blli[0] = blli; + if (setsockopt(s,SOL_ATM,SO_ATMSAP,&atmsap,sizeof(atmsap)) < 0) { + EVENT(EM_NERR,("conn.c::cm_sap_svc_setup setsockop(SO_ATMSAP)\n")); + (void) close(s); + return -1; + } ret = bind(s, (struct sockaddr *)&us, sizeof(us)); if (ret<0) { @@ -372,7 +380,7 @@ } if (EMASK & EM_DEBUG) - disp_sockaddr(&(p_conn_info->addr)); + disp_sockaddr(p_conn_info); EVENT(EM_EVENT,("Call to %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x\n", p_conn_info->addr.sas_addr.prv[0]&0xff, @@ -534,12 +542,13 @@ EVENT(EM_DEBUG,("Cm_sap_link_status_get\n")); assert(sap_handle); - if ((s=socket(AF_ATMSVC, SOCK_DGRAM, ATM_AAL5))<0) { + if ((s=socket(AF_ATMSVC, SOCK_DGRAM, 0))<0) { /* Socket creation failure -> not capable of running LE */ EVENT(EM_SERR,("Not capable of creating ATM socket.")); *p_link_state = LINK_DOWN; exit(-1); } + close(s); *p_link_state = LINK_SIG_UP; } @@ -547,7 +556,6 @@ svcinit_conn_info(CONN_INFO *p_svc_conn_info) { memset(p_svc_conn_info,0,sizeof(CONN_INFO)); - p_svc_conn_info->addr.sas_addr.blli = &(p_svc_conn_info->blli); } /* Callbacks for connections */ @@ -620,12 +628,12 @@ conn_get_fds(fd_set *fds) { Conn_t *conn; - char *buff, *ch; + char *buff = NULL, *ch = NULL; /* once again, silence gcc 2.7.2.1 */ conn = connlist; if (EMASK & EM_DEBUG) { - buff = (char*)mem_alloc(EINST,1024); + buff = (char*)mem_alloc(EINST, 1024); ch = buff; } while (conn) { @@ -647,7 +655,7 @@ conn_get_connecting_fds(fd_set *fds) { Conn_t *conn; - char *buff, *ch; + char *buff = NULL, *ch = NULL; /* once again, silence gcc 2.7.2.1 */ conn = connlist; @@ -879,11 +887,12 @@ int fd, ret, len; Conn_t *conn; CONN_INFO *conn_info; + struct atm_sap atmsap; conn_info = (CONN_INFO *)mem_alloc(EINST, sizeof(CONN_INFO)); EVENT(EM_DEBUG,("conn_create_listensocket\n")); - fd = socket(PF_ATMSVC, SOCK_DGRAM, ATM_AAL5); + fd = socket(PF_ATMSVC, SOCK_DGRAM, 0); if (fd < 0) { EVENT(EM_NERR,("Socket failed: %s\n",strerror(errno))); return -1; @@ -891,6 +900,7 @@ memset(conn_info , 0, sizeof(CONN_INFO)); + conn_info->conqos.aal = ATM_AAL5; conn_info->conqos.txtp.traffic_class = ATM_UBR; conn_info->conqos.rxtp.traffic_class = ATM_UBR; @@ -926,7 +936,6 @@ close(fd); return -1; } - conn_info->addr.sas_addr.blli = &conn_info->blli; conn_info->blli.l3_proto = ATM_L3_TR9577; conn_info->blli.l3.tr9577.ipi = NLPID_IEEE802_1_SNAP; conn_info->blli.l3.tr9577.snap[0] = 0x00; @@ -939,8 +948,16 @@ len = sizeof(struct sockaddr_atmsvc); if (EMASK & EM_DEBUG) - disp_sockaddr(&conn_info->addr); - + disp_sockaddr(conn_info); + + memset(&atmsap, 0, sizeof(struct atm_sap)); + atmsap.blli[0] = conn_info->blli; + if (setsockopt(fd,SOL_ATM,SO_ATMSAP,&atmsap,sizeof(atmsap)) < 0) { + EVENT(EM_NERR,("conn.c::conn_create_listensocket setsockop(SO_ATMSAP)\n")); + (void) close(fd); + return -1; + } + ret = bind(fd, (struct sockaddr *)&conn_info->addr, len); if (ret != 0) { EVENT(EM_NERR,("Bind failed: %s\n",strerror(errno))); diff -ur --new-file old/atm/led/conn.h new/atm/led/conn.h --- old/atm/led/conn.h Wed Apr 16 14:17:27 1997 +++ new/atm/led/conn.h Thu Feb 26 21:25:29 1998 @@ -10,6 +10,7 @@ #include #include #include +#include #include "af_lane.h" diff -ur --new-file old/atm/led/kernel_itf.c new/atm/led/kernel_itf.c --- old/atm/led/kernel_itf.c Wed Apr 16 14:17:27 1997 +++ new/atm/led/kernel_itf.c Sun Feb 1 13:23:03 1998 @@ -34,7 +34,7 @@ #include #include #include - +#include /* for malloc() and free() */ /* Atm includes */ #include #include @@ -93,28 +93,41 @@ return itf_num; } +/* + * LANE2: The messages to/from kernel can be variable size. + * We now have to be prepared to malloc() the right size msg + * + */ int kernel_sendmsg(atmlec_msg_type type, unsigned char *mac_addr, unsigned char *atm_addr, struct atmlec_config_msg *config, - unsigned long flag) + unsigned long flag, char *data, int datalen) { - struct atmlec_msg mesg; + struct atmlec_msg *mesg; - memset(&mesg, 0, sizeof(mesg)); - mesg.type = type; + mesg = (struct atmlec_msg *)malloc(sizeof(struct atmlec_msg) + datalen); + + memset(mesg, 0, sizeof(struct atmlec_msg) + datalen); + mesg->type = type; if (type != l_config) { if (mac_addr) - memcpy(mesg.content.normal.mac_addr, mac_addr, ETH_ALEN); + memcpy(&mesg->content.normal.mac_addr, mac_addr, ETH_ALEN); if (atm_addr) - memcpy(mesg.content.normal.atm_addr, atm_addr, ATM_ESA_LEN); - mesg.content.normal.flag = flag; + memcpy(&mesg->content.normal.atm_addr, atm_addr, ATM_ESA_LEN); + mesg->content.normal.flag = flag; } else - memcpy(&mesg.content.config, config, sizeof(struct atmlec_config_msg)); + memcpy(&mesg->content.config, config, sizeof(struct atmlec_config_msg)); + + mesg->sizeoftlvs = datalen; + if (datalen > 0) + memcpy(mesg + 1, data, datalen); /* Add the TLVs */ - if (write(lec_socket, &mesg, sizeof(mesg))<0) { + if (write(lec_socket, mesg, sizeof(struct atmlec_msg) + datalen)<0) { EVENT(EM_SERR,("Write to kernel failed!\n")); + free(mesg); return -1; } + free(mesg); return 0; } @@ -160,16 +173,34 @@ { struct atmlec_msg mesg; - EVENT(EM_DEBUG,("Received message from kernel\n")); if (read(lec_socket, &mesg, sizeof(mesg))<0) { EVENT(EM_SERR,("Read from kernel socket failed:%s\n",strerror(errno))); return; } + EVENT(EM_DEBUG,("Received message %d from kernel: %s, sizeoftlvs=%d\n", + mesg.type, get_mesg_type_str(mesg.type), + mesg.sizeoftlvs)); if (callback_funcs[mesg.type]) { callback_funcs[mesg.type](&mesg); } else EVENT(EM_NERR,("No handler for message type:%s\n", get_mesg_type_str(mesg.type))); +} + +/* + * LANE2: LE_ARP frames can now have TLVs with them. Use this after + * l_arp_xmt message from kernel to read the TLVs that follow. + */ +int read_from_kernel (char *buff, int size) +{ + int retval; + + fprintf(stderr, "read_from_kernel: about to read\n"); + retval = read(lec_socket, buff, size); + fprintf(stderr, "read_from_kernel: read returned %d\n", retval); + if (retval < 0) + EVENT(EM_SERR,("Read for extra data from kernel socket failed:%s\n",strerror(errno))); + return retval; } /* diff -ur --new-file old/atm/led/kernel_itf.h new/atm/led/kernel_itf.h --- old/atm/led/kernel_itf.h Wed Apr 16 14:17:27 1997 +++ new/atm/led/kernel_itf.h Sun Feb 1 13:23:03 1998 @@ -36,9 +36,10 @@ int kernel_init(unsigned char *mac_addr, int itf_num); int kernel_sendmsg(atmlec_msg_type type, unsigned char *mac_addr, unsigned char *atm_addr, struct atmlec_config_msg *config, - unsigned long flag); + unsigned long flag, char *data, int datalen); int kernel_register_callback(atmlec_msg_type type, kernel_callback callback); void kernel_dispatch_handlers(void); +int read_from_kernel (char *buff, int size); #endif /* KERNEL_ITF_H */ /* diff -ur --new-file old/atm/led/lane_atm.h new/atm/led/lane_atm.h --- old/atm/led/lane_atm.h Thu Jan 1 01:00:00 1970 +++ new/atm/led/lane_atm.h Wed Nov 19 12:59:16 1997 @@ -0,0 +1,191 @@ +/************************************************************************* + (c) Copyright. Digital Equipment Corporation, 1995. All Rights + Reserved. + + Permission is hereby granted to use, copy, modify, or enhance this + software freely, as long as the foregoing copyright of Digital Equipment + Corporation and this notice are retained on the software. This + software may not be distributed or sublicensed for a fee. Digital + makes this software available "AS IS" and without warranties of any + kind. + *************************************************************************/ +/* + * Marko Kiiskila carnil@cs.tut.fi + * + * Tampere University of Technology - Telecommunications Laboratory + * + * Permission to use, copy, modify and distribute this + * software and its documentation is hereby granted, + * provided that both the copyright notice and this + * permission notice appear in all copies of the software, + * derivative works or modified versions, and any portions + * thereof, that both notices appear in supporting + * documentation, and that the use of this software is + * acknowledged in any publications resulting from using + * the software. + * + * TUT ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION AND DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS + * SOFTWARE. + * + */ + +/* +* Module Name: +* lane_atm.h +* +* Abstract: +* This module defines ATM specific types and constants. +* +* Authors: +* TLR - Theodore L. Ross +* +* Modification History: +* Date Name Description +* 16-Sep-94 TLR Created. +* 31-Oct-94 DMW Use INT8 instead of UCHAR, add definition for PREFIX. +* Change definition for ADDR_ATM to use basic types and +* to not have selector be an array. +* 10-Jan-95 TLR Added address copy and compare methods. +* 08-Sep-95 TLR Updated QOS definitions and removed buggy atm_is_greater. +* 17-Oct-97 hessu Changed the filename from atm.h to lane_atm.h +* +* Description: +* Only ATM specific types should be defined here. +--*/ +#ifndef LANE_ATM_H +#define LANE_ATM_H + +/* General address related definitions. */ + +typedef UINT8 ADDR_48[6]; /* MAC Address. */ +typedef UINT8 ESI[6]; /* End System Identifier */ +typedef UINT8 PREFIX[13]; /* Network Prefix. */ + +/* Type for ATM Address. */ + +typedef struct + { + PREFIX prefix; /* Network Prefix set by the switch. */ + ESI esi; /* ESI or MAC Addr */ + UINT8 sel; /* Selector */ + } ADDR_ATM; + +typedef union + { + struct + { + UINT8 cpcs_uu; + UINT8 clp; + } aal5_data; + } AAL_DATA; + +#define ESI_COPY(from, to) \ + { \ + (to)[0] = (from)[0]; \ + (to)[1] = (from)[1]; \ + (to)[2] = (from)[2]; \ + (to)[3] = (from)[3]; \ + (to)[4] = (from)[4]; \ + (to)[5] = (from)[5]; \ + } + +#define ESI_IS_BCAST(esi) (((esi)[0] == 0xff) && \ + ((esi)[1] == 0xff) && \ + ((esi)[2] == 0xff) && \ + ((esi)[3] == 0xff) && \ + ((esi)[4] == 0xff) && \ + ((esi)[5] == 0xff)) + +#define ATM_COPY(from, to) \ + { \ + (to).prefix[0] = (from).prefix[0]; \ + (to).prefix[1] = (from).prefix[1]; \ + (to).prefix[2] = (from).prefix[2]; \ + (to).prefix[3] = (from).prefix[3]; \ + (to).prefix[4] = (from).prefix[4]; \ + (to).prefix[5] = (from).prefix[5]; \ + (to).prefix[6] = (from).prefix[6]; \ + (to).prefix[7] = (from).prefix[7]; \ + (to).prefix[8] = (from).prefix[8]; \ + (to).prefix[9] = (from).prefix[9]; \ + (to).prefix[10] = (from).prefix[10]; \ + (to).prefix[11] = (from).prefix[11]; \ + (to).prefix[12] = (from).prefix[12]; \ + (to).esi[0] = (from).esi[0]; \ + (to).esi[1] = (from).esi[1]; \ + (to).esi[2] = (from).esi[2]; \ + (to).esi[3] = (from).esi[3]; \ + (to).esi[4] = (from).esi[4]; \ + (to).esi[5] = (from).esi[5]; \ + (to).sel = (from).sel; \ + } + +#define ATM_COPY_NULL(to) \ + { \ + (to).prefix[0] = 0; \ + (to).prefix[1] = 0; \ + (to).prefix[2] = 0; \ + (to).prefix[3] = 0; \ + (to).prefix[4] = 0; \ + (to).prefix[5] = 0; \ + (to).prefix[6] = 0; \ + (to).prefix[7] = 0; \ + (to).prefix[8] = 0; \ + (to).prefix[9] = 0; \ + (to).prefix[10] = 0; \ + (to).prefix[11] = 0; \ + (to).prefix[12] = 0; \ + (to).esi[0] = 0; \ + (to).esi[1] = 0; \ + (to).esi[2] = 0; \ + (to).esi[3] = 0; \ + (to).esi[4] = 0; \ + (to).esi[5] = 0; \ + (to).sel = 0; \ + } + +#define ATM_EQUAL(a1, a2) (((a1).sel == (a2).sel) && \ + ((a1).esi[5] == (a2).esi[5]) && \ + ((a1).esi[4] == (a2).esi[4]) && \ + ((a1).esi[3] == (a2).esi[3]) && \ + ((a1).esi[2] == (a2).esi[2]) && \ + ((a1).esi[1] == (a2).esi[1]) && \ + ((a1).esi[0] == (a2).esi[0]) && \ + ((a1).prefix[12] == (a2).prefix[12]) && \ + ((a1).prefix[11] == (a2).prefix[11]) && \ + ((a1).prefix[10] == (a2).prefix[10]) && \ + ((a1).prefix[9] == (a2).prefix[9]) && \ + ((a1).prefix[8] == (a2).prefix[8]) && \ + ((a1).prefix[7] == (a2).prefix[7]) && \ + ((a1).prefix[6] == (a2).prefix[6]) && \ + ((a1).prefix[5] == (a2).prefix[5]) && \ + ((a1).prefix[4] == (a2).prefix[4]) && \ + ((a1).prefix[3] == (a2).prefix[3]) && \ + ((a1).prefix[2] == (a2).prefix[2]) && \ + ((a1).prefix[1] == (a2).prefix[1]) && \ + ((a1).prefix[0] == (a2).prefix[0])) + +#define ATM_EQUAL_NULL(a1) (((a1).sel == 0) && \ + ((a1).esi[5] == 0) && \ + ((a1).esi[4] == 0) && \ + ((a1).esi[3] == 0) && \ + ((a1).esi[2] == 0) && \ + ((a1).esi[1] == 0) && \ + ((a1).esi[0] == 0) && \ + ((a1).prefix[12] == 0) && \ + ((a1).prefix[11] == 0) && \ + ((a1).prefix[10] == 0) && \ + ((a1).prefix[9] == 0) && \ + ((a1).prefix[8] == 0) && \ + ((a1).prefix[7] == 0) && \ + ((a1).prefix[6] == 0) && \ + ((a1).prefix[5] == 0) && \ + ((a1).prefix[4] == 0) && \ + ((a1).prefix[3] == 0) && \ + ((a1).prefix[2] == 0) && \ + ((a1).prefix[1] == 0) && \ + ((a1).prefix[0] == 0)) + +#endif /* LANE_ATM_H */ diff -ur --new-file old/atm/led/le_disp.c new/atm/led/le_disp.c --- old/atm/led/le_disp.c Wed Apr 16 14:17:27 1997 +++ new/atm/led/le_disp.c Sun Feb 1 13:23:04 1998 @@ -39,11 +39,12 @@ #include #include "codes.h" #include "g_types.h" -#include "atm.h" +#include "lane_atm.h" #include "system.h" #include "g_endian.h" #include "af_lane.h" #include "le_disp.h" +#include "svc_info.h" /* for CONN_INFO */ const char *disp_status_text (UINT16 status) { @@ -284,27 +285,23 @@ printf ("Illegal Frame\n"); } -void disp_sockaddr(struct sockaddr_atmsvc *addr) +void disp_sockaddr(CONN_INFO *p_conn_info) { int i; - printf("Sas_family:%d\n\tAddress:",addr->sas_family); + + printf("Sas_family:%d\n\tAddress:", p_conn_info->addr.sas_family); for(i=0;i<20;i++) { - printf("%2.2x ",addr->sas_addr.prv[i]); + printf("%2.2x ",p_conn_info->addr.sas_addr.prv[i]); } - if (!addr->sas_addr.blli) { - printf("No blli information\n"); - fflush(stdout); - } else { - printf("\nBlli:\n\t"); - printf("l2_proto:%d\n\t",addr->sas_addr.blli->l2_proto); - fflush(stdout); - printf("l3_proto:%d\n\t\t",addr->sas_addr.blli->l3_proto); - fflush(stdout); - printf("ipi:%x\tsnap:",addr->sas_addr.blli->l3.tr9577.ipi); - fflush(stdout); - for(i=0;i<5;i++) { - printf("%2.2x ",addr->sas_addr.blli->l3.tr9577.snap[i]); - } - printf("\n"); + printf("\nBlli:\n\t"); + printf("l2_proto:%d\n\t",p_conn_info->blli.l2_proto); + fflush(stdout); + printf("l3_proto:%d\n\t\t",p_conn_info->blli.l3_proto); + fflush(stdout); + printf("ipi:%x\tsnap:",p_conn_info->blli.l3.tr9577.ipi); + fflush(stdout); + for(i=0;i<5;i++) { + printf("%2.2x ",p_conn_info->blli.l3.tr9577.snap[i]); } + printf("\n"); } diff -ur --new-file old/atm/led/le_disp.h new/atm/led/le_disp.h --- old/atm/led/le_disp.h Wed Apr 16 14:17:27 1997 +++ new/atm/led/le_disp.h Wed Nov 19 12:59:15 1997 @@ -37,6 +37,7 @@ * */ #include +#include "svc_info.h" const char *disp_status_text (UINT16 status); @@ -48,4 +49,4 @@ UINT32 length, const char *text); -void disp_sockaddr(struct sockaddr_atmsvc *addr); +void disp_sockaddr(CONN_INFO *p_conn_info); diff -ur --new-file old/atm/led/lec.h new/atm/led/lec.h --- old/atm/led/lec.h Wed Apr 16 14:17:27 1997 +++ new/atm/led/lec.h Wed Nov 19 12:59:15 1997 @@ -51,7 +51,7 @@ * Dependencies: * types.h - Generally used type definitions. * codes.h - Completion codes. -* atm.h - ATM specific definitions and types. +* lane_atm.h - ATM specific definitions and types. * */ @@ -80,7 +80,7 @@ */ #ifndef LEC_H #define LEC_H -#include "atm.h" +#include "lane_atm.h" typedef enum { diff -ur --new-file old/atm/led/lec_arp.c new/atm/led/lec_arp.c --- old/atm/led/lec_arp.c Wed Apr 16 14:17:27 1997 +++ new/atm/led/lec_arp.c Sun Feb 1 13:23:04 1998 @@ -37,7 +37,7 @@ #include "g_types.h" /* General Purpose Types */ #include "codes.h" /* Return Status Codes */ -#include "atm.h" /* ATM Specific Definitions */ +#include "lane_atm.h" /* ATM Specific Definitions */ #include "utl.h" /* General Purpose Utilities */ #include "utl_os.h" /* Operating System Utilities */ #include "system.h" @@ -79,6 +79,10 @@ static LA_CONTEXT lec_arp_context; +/* + * LE_ARP request from kernel + * LANE2: LE_ARP frames can now contain variable size TLVs + */ static void kernel_arp_xmt_callback(struct atmlec_msg *mesg) { @@ -88,7 +92,8 @@ to_pass = (ESI*)mesg->content.normal.mac_addr; utl_list_traverse(lec_arp_context.elan_list, p_elan) { - lec_arp_context.arp_xmt_callback(p_elan->lc_elan_handle, *to_pass); + lec_arp_context.arp_xmt_callback(p_elan->lc_elan_handle, + *to_pass, mesg->sizeoftlvs); } } @@ -102,7 +107,7 @@ lec_arp_context.flush_xmt_callback(p_elan->lc_elan_handle, to_pass,&dumb); EVENT(EM_DEBUG,("Setting flush transaction id to %lx\n",dumb)); kernel_sendmsg(l_flush_tran_id, NULL, to_pass, - NULL, dumb); + NULL, dumb, NULL, 0); } } @@ -222,7 +227,7 @@ conf_mesg.arp_response_time = le_arp_response_time; conf_mesg.flush_timeout = flush_timeout; conf_mesg.path_switching_delay = path_switching_delay; - kernel_sendmsg(l_config, NULL, NULL, &conf_mesg, 0); + kernel_sendmsg(l_config, NULL, NULL, &conf_mesg, 0, NULL, 0); } STATUS @@ -231,20 +236,27 @@ BOOLEAN permanent) { kernel_sendmsg(l_addr_delete, NULL, atm_addr, NULL, - permanent==TRUE?1:0); + permanent==TRUE?1:0, NULL, 0); return STATUS_K_SUCCESS; } +/* + * LANE2: tlv_list passing added + * + */ void la_arp_update(HANDLE la_elan_handle, ESI esi, ADDR_ATM addr_atm, - BOOLEAN remote_flag) + BOOLEAN remote_flag, + char *tlv_list, + int sizeoftlvs) { EVENT(EM_DEBUG,("ARP update for %2.2x%2.2x%2.2x%2.2x%2.2x%2.2x\n", esi[0],esi[1],esi[2],esi[3],esi[4],esi[5])); kernel_sendmsg(l_arp_update, (unsigned char *)esi, - (unsigned char *)&addr_atm, NULL, remote_flag==TRUE?1:0); + (unsigned char *)&addr_atm, NULL, remote_flag==TRUE?1:0, + tlv_list, sizeoftlvs); } void @@ -253,7 +265,7 @@ { EVENT(EM_DEBUG,("Flush complete for tran_id %lx\n", tran_id)); kernel_sendmsg(l_flush_complete, NULL, - NULL, NULL, tran_id); + NULL, NULL, tran_id, NULL, 0); } void @@ -261,7 +273,8 @@ BOOLEAN topology_change_flag) { kernel_sendmsg(l_topology_change, NULL, NULL, NULL, - topology_change_flag==TRUE?1:0); + topology_change_flag==TRUE?1:0, + NULL, 0); } diff -ur --new-file old/atm/led/lec_arp.h new/atm/led/lec_arp.h --- old/atm/led/lec_arp.h Wed Apr 16 14:17:27 1997 +++ new/atm/led/lec_arp.h Sun Feb 1 13:23:05 1998 @@ -195,6 +195,7 @@ * Arguments: * lc_elan_handle - (IN) Handle of LEC CTRL instance to be used. * esi - (IN) 48-bit address for LE-ARP. +* sizeoftlvs - (IN) LANE2: total length of TLVs to send * * Returns: * None @@ -207,7 +208,8 @@ * --*/ typedef void (*ARP_XMT_CALLBACK) (HANDLE lc_elan_handle, - ESI esi); + ESI esi, + int sizeoftlvs); /*++ * ====================== @@ -520,6 +522,8 @@ * esi - (IN) MAC Address in updated mapping. * addr_atm - (IN) ATM Address in the updated mapping. * remote_flag - (IN) Remote flag contained in the LE-ARP response frame. +* tlv_list - (IN) LANE2: LE-ARP frames can now contain TLVs +* sizeoftlvs - (IN) LANE2: The length of tlv_list in bytes * * Returns: * None @@ -532,11 +536,14 @@ * a change from the original mapping (i.e. the ATM address is different from * what was originally in the mapping), the old mapping is discarded and the * flush mechanism is invoked to facilitate the path switch. +* LANE2: The TLV association is also up-to-date --*/ void la_arp_update (HANDLE la_elan_handle, ESI esi, ADDR_ATM addr_atm, - BOOLEAN remote_flag); + BOOLEAN remote_flag, + char *tlv_list, + int sizeoftlvs); /*++ * ===================== diff -ur --new-file old/atm/led/lec_ctrl.c new/atm/led/lec_ctrl.c --- old/atm/led/lec_ctrl.c Tue Apr 22 17:47:23 1997 +++ new/atm/led/lec_ctrl.c Mon Feb 2 14:35:01 1998 @@ -75,7 +75,7 @@ #include "g_endian.h" /* Host/Network Data Conversion Routines */ #include "utl.h" /* General Purpose Utilities */ #include "utl_os.h" /* Operating System Utilities */ -#include "atm.h" /* ATM Specific Definitions and Macros */ +#include "lane_atm.h" /* ATM Specific Definitions and Macros */ #include "atmsap.h" /* ATM SAP definition */ #include "system.h" /* ATM Subsystem Specific Stuff */ #include "g_event.h" @@ -91,6 +91,7 @@ #include "lec_arp.h" /* LEC_ARP Module Interface */ #include "lec_ctrl.h" /* LEC_CTRL Module Interface */ #include "le_disp.h" +#include "kernel_itf.h" /* read_from_kernel() */ #define EMOD MOD_LEC_CTRL #define EINST "lec_ctrl.c" @@ -537,6 +538,9 @@ * STATUS_K_MISMATCH. */ + if (p_conn_info->blli.l2_proto == ATM_L2_ISO8802) /* 0x12 */ + return STATUS_K_REJECT; /* LANE2: LLC-muxed VCCs not supported here */ + /* Make sure the first bytes are 6B.40.80.80.00.A0.3E */ @@ -1713,26 +1717,50 @@ /*++ * ============== -* = lc_arp_xmt = +* = lc_arp_xmt = arp request from kernel * ============== +* +* LANE2: LE_ARP_FRAME can now contain TLVs and therefore has +* variable size. Total length of TLVs is in sizeoftlvs +* --*/ static void lc_arp_xmt (HANDLE lc_elan_handle, - ESI esi) + ESI esi, int sizeoftlvs) { - LC_ELAN_CONTEXT *p_elan; - LE_ARP_FRAME frame; - STATUS status; + LC_ELAN_CONTEXT *p_elan; + LE_ARP_FRAME *frame; + STATUS status = 0; /* silence gcc 2.7.2.1 */ + size_t framelength; + int retval; + char *buff; + + framelength = sizeof(LE_ARP_FRAME) + sizeoftlvs; p_elan = (LC_ELAN_CONTEXT *) lc_elan_handle; - memset(&frame, 0, sizeof (LE_ARP_FRAME)); + frame = (LE_ARP_FRAME*)os_mem_alloc(framelength); + memset(frame, 0, framelength); - lc_ctrl_hdr_make (lc_elan_handle, &frame.hdr, LE_ARP_REQ); + lc_ctrl_hdr_make (lc_elan_handle, &frame->hdr, LE_ARP_REQ); - frame.src_lan_dst.tag = hton16 (TAG_NOT_PRESENT); - frame.target_lan_dst.tag = hton16 (TAG_MAC_ADDR); - ESI_COPY (esi, frame.target_lan_dst.mac_addr); - ATM_COPY (p_elan->lec_state.c1_my_atm_addr, frame.src_atm_addr); + frame->src_lan_dst.tag = hton16 (TAG_NOT_PRESENT); + frame->target_lan_dst.tag = hton16 (TAG_MAC_ADDR); + ESI_COPY (esi, frame->target_lan_dst.mac_addr); + ATM_COPY (p_elan->lec_state.c1_my_atm_addr, frame->src_atm_addr); + + if (sizeoftlvs != 0) { + buff = os_mem_alloc(sizeoftlvs); + retval = read_from_kernel(buff, sizeoftlvs); + if (retval != sizeoftlvs) + EVENT (EM_SERR, ("lc_arp_xmt(): short read\n")); + fprintf(stderr, "TLV-ARP-DEBUG: 0x"); + for (retval = 0; retval < sizeoftlvs; retval++) + fprintf(stderr, "%x", buff[retval]); + fprintf(stderr, "\n"); + memcpy(frame + 1, buff, sizeoftlvs); + fprintf(stderr, "lc_arp_xmt(): after memcpy\n"); + os_mem_dealloc(buff); + } EVENT (EM_XDATA, ("Sending LE-ARP for address: %02x-%02x-%02x-%02x-%02x-%02x\n", esi[0], esi[1], esi[2], esi[3], esi[4], esi[5])); @@ -1741,11 +1769,12 @@ if (p_elan->sm_state == S_OPERATIONAL) { status = cm_sap_xmt_vc (p_elan->ctrl_direct_conn_handle, - &frame, - sizeof (frame), + frame, + framelength, USER_DATA_INTERNAL, NULL); } + os_mem_dealloc(frame); if (status != STATUS_K_SUCCESS) p_elan->ctrl_xmt_failure_count += 1; else @@ -1763,7 +1792,7 @@ { LC_ELAN_CONTEXT *p_elan; LE_FLUSH_FRAME frame; - STATUS status; + STATUS status = 0; /* silence gcc 2.7.2.1 */ UINT32 *p_tran_id; int i; @@ -2531,6 +2560,8 @@ case STATUS_K_REJECT : + if (p_conn_info->blli.l2_proto == ATM_L2_ISO8802) /* 0x12 */ + EVENT (EM_EVENT, ("Rejecting LANE2 LLC-muxed VCC - not supported.\n")); *p_reject_reason = CAUSE_NORMAL; /*???*/ return FALSE; @@ -3049,6 +3080,10 @@ * =============== * = lec_arp_rsp = * =============== +* +* LANE2: LE_ARP_FRAME can now contain TLVs and therefore has +* variable size. +* --*/ STATIC void lec_arp_rsp (LC_ELAN_CONTEXT *p_elan, @@ -3056,11 +3091,13 @@ UINT32 length) { LE_ARP_FRAME *frame; - + int sizeoftlvs; + frame = (LE_ARP_FRAME *)p_packet; if (length < sizeof (LE_ARP_FRAME)) return; + sizeoftlvs = length - sizeof(LE_ARP_FRAME); if (frame->hdr.status == ntoh16 (LE_STATUS_SUCCESS)) { switch (ntoh16 (frame->target_lan_dst.tag)) { @@ -3087,7 +3124,9 @@ frame->target_lan_dst.mac_addr, frame->target_atm_addr, (ntoh16(frame->hdr.flags) & - LE_FLAG_REMOTE_ADDR) ? TRUE : FALSE); + LE_FLAG_REMOTE_ADDR) ? TRUE : FALSE, + (char *)frame + 1, + sizeoftlvs); } } break; diff -ur --new-file old/atm/led/main.c new/atm/led/main.c --- old/atm/led/main.c Tue Apr 22 21:34:01 1997 +++ new/atm/led/main.c Sun Feb 1 13:23:06 1998 @@ -175,7 +175,7 @@ elan = (LD_ELAN_CONTEXT *)elan_handle; elan->lec_id = lec_id; - kernel_sendmsg(l_set_lecid, NULL, NULL, NULL, lec_id); + kernel_sendmsg(l_set_lecid, NULL, NULL, NULL, lec_id, NULL, 0); } void @@ -622,7 +622,7 @@ current_timer = timer_find_soonest(); timeout = timer_get_expiration(current_timer); if (timeout) { - EVENT(EM_DEBUG,("Sleeping %d secs....\n",timeout->tv_sec)); + EVENT(EM_DEBUG,("Sleeping %ld secs....\n",(long)timeout->tv_sec)); } else { EVENT(EM_DEBUG,("No timers pending...\n")); } @@ -631,7 +631,8 @@ conn_get_fds(&fds); FD_ZERO(&efds); conn_get_connecting_fds(&efds); - poll_ret = select(FD_SETSIZE, &fds, &efds, &efds, timeout); + /* the NULL argument used to be &efds, changed in pre-0.33-x */ + poll_ret = select(FD_SETSIZE, &fds, &efds, NULL, timeout); EVENT(EM_DEBUG,("Selected .....\n\n\n")); if (poll_ret < 0) { perror("select"); diff -ur --new-file old/atm/led/timers.c new/atm/led/timers.c --- old/atm/led/timers.c Wed Apr 16 14:17:27 1997 +++ new/atm/led/timers.c Wed Nov 19 12:59:16 1997 @@ -198,11 +198,11 @@ if (to_get->alarm_time) { gettimeofday(&g_timer, &tz); - EVENT(EM_TIMER,("G_timer:%d sec %d usec\n", - g_timer.tv_sec,g_timer.tv_usec)); - EVENT(EM_TIMER,("Timer :%d sec %d usec\n", - to_get->alarm_time->tv_sec, - to_get->alarm_time->tv_usec)); + EVENT(EM_TIMER,("G_timer:%ld sec %ld usec\n", + (long)g_timer.tv_sec,(long)g_timer.tv_usec)); + EVENT(EM_TIMER,("Timer :%ld sec %ld usec\n", + (long)to_get->alarm_time->tv_sec, + (long)to_get->alarm_time->tv_usec)); if (g_timer.tv_sec > (to_get->alarm_time)->tv_sec || (g_timer.tv_sec == (to_get->alarm_time)->tv_sec && g_timer.tv_usec >= (to_get->alarm_time)->tv_usec)) { @@ -217,7 +217,8 @@ g_timer.tv_usec = (to_get->alarm_time)->tv_usec - g_timer.tv_usec; } - EVENT(EM_TIMER,("Return:%d sec %d usec\n",g_timer.tv_sec,g_timer.tv_usec)); + EVENT(EM_TIMER,("Return:%ld sec %ld usec\n", + (long)g_timer.tv_sec,(long)g_timer.tv_usec)); return &g_timer; } else return NULL; @@ -248,10 +249,10 @@ printf("Timer usage:\n"); for(tmp=timerlist;tmp;tmp=tmp->next) - printf("\tCallback %p Context:%p %d sec %d usec\n", + printf("\tCallback %p Context:%p %ld sec %ld usec\n", tmp->callback, tmp->context, - tmp->alarm_time?tmp->alarm_time->tv_sec:0, - tmp->alarm_time?tmp->alarm_time->tv_usec:0); + tmp->alarm_time?(long)tmp->alarm_time->tv_sec:0, + tmp->alarm_time?(long)tmp->alarm_time->tv_usec:0); } /* diff -ur --new-file old/atm/lib/Makefile new/atm/lib/Makefile --- old/atm/lib/Makefile Wed Nov 5 02:13:05 1997 +++ new/atm/lib/Makefile Thu Mar 5 16:14:49 1998 @@ -1,5 +1,5 @@ ATM_OBJS=text2atm.o atm2text.o atmequal.o sdu2cell.o text2qos.o qos2text.o \ - qosequal.o sap2text.o text2sap.o misc.o + qosequal.o sap2text.o text2sap.o sapequal.o misc.o ifeq (/usr/lib/libresolv.a,$(wildcard /usr/lib/libresolv.a)) ATM_OBJS += ans_l.o else @@ -10,6 +10,7 @@ PGMS=#test GENLIBS=libatm.a libatmd.a libarequipa.a SYSHDR=atm.h atmd.h atmsap.h arequipa.h +OPTSYSHDR=stdint.h all: libatm.a libatmd.a libarequipa.a diff -ur --new-file old/atm/lib/arequipa.h new/atm/lib/arequipa.h --- old/atm/lib/arequipa.h Thu Oct 9 16:55:12 1997 +++ new/atm/lib/arequipa.h Fri Feb 27 19:38:16 1998 @@ -1,10 +1,11 @@ /* arequipa.h - AREQUIPA support functions */ -/* Written 1996,1997 by Jean-Michel Pittet and Werner Almesberger, EPFL-LRC */ +/* Written 1996-1998 by Jean-Michel Pittet and Werner Almesberger, + EPFL-LRC/ICA */ -#ifndef AREQUIPA_H -#define AREQUIPA_H +#ifndef _AREQUIPA_H +#define _AREQUIPA_H #include diff -ur --new-file old/atm/lib/atm.h new/atm/lib/atm.h --- old/atm/lib/atm.h Wed Nov 5 22:33:56 1997 +++ new/atm/lib/atm.h Thu Mar 5 16:15:36 1998 @@ -1,10 +1,10 @@ /* atm.h - Functions useful for ATM applications */ -/* Written 1995-1997 by Werner Almesberger, EPFL-LRC */ +/* Written 1995-1998 by Werner Almesberger, EPFL-LRC/ICA */ -#ifndef ATM_H -#define ATM_H +#ifndef _ATM_H +#define _ATM_H #include #include @@ -12,6 +12,7 @@ #define HOSTS_ATM "/etc/hosts.atm" +/* text2atm flags */ #define T2A_PVC 1 /* address is PVC */ #define T2A_SVC 2 /* address is SVC */ #define T2A_UNSPEC 4 /* allow unspecified parts in PVC address */ @@ -21,22 +22,33 @@ #define T2A_REMOTE 64 /* OBSOLETE */ #define T2A_LOCAL 128 /* don't use ANS */ +/* atm2text flags */ #define A2T_PRETTY 1 /* add syntactic sugar */ #define A2T_NAME 2 /* attempt name lookup */ #define A2T_REMOTE 4 /* OBSOLETE */ #define A2T_LOCAL 8 /* don't use ANS */ +/* atm_equal flags */ #define AXE_WILDCARD 1 /* allow wildcard match */ #define AXE_PRVOPT 2 /* private part is optional */ +/* text2qos flags */ #define T2Q_DEFAULTS 1 /* structure contains default values */ -#define S2T_NAME 1 /* attempt name lookup */ -#define S2T_LOCAL 2 /* we may support NIS or such in the future */ - +/* text2sap flags */ #define T2S_NAME 1 /* attempt name lookup */ #define T2S_LOCAL 2 /* we may support NIS or such in the future */ +/* sap2text flags */ +#define S2T_NAME 1 /* attempt name lookup */ +#define S2T_LOCAL 2 /* we may support NIS or such in the future */ + +/* sap_equal flags */ +#define SXE_COMPATIBLE 1 /* check for compatibility instead of identity*/ +#define SXE_NEGOTIATION 2 /* allow negotiation; requires SXE_COMPATIBLE; + assumes "a" defines the available + capabilities */ +#define SXE_RESULT 4 /* return selected SAP */ #define MAX_ATM_ADDR_LEN (2*ATM_ESA_LEN+ATM_E164_LEN+5) /* 4 dots, 1 plus */ @@ -58,8 +70,9 @@ int qos2text(char *buffer,int length,const struct atm_qos *qos,int flags); int qos_equal(const struct atm_qos *a,const struct atm_qos *b); -int sap2text(char *buffer,int length,const struct atm_sap *sap,int flags); int text2sap(const char *text,struct atm_sap *sap,int flags); +int sap2text(char *buffer,int length,const struct atm_sap *sap,int flags); +int sap_equal(const struct atm_sap *a,const struct atm_sap *b,int flags,...); int __atmlib_fetch(const char **pos,...); /* internal use only */ diff -ur --new-file old/atm/lib/atmd.h new/atm/lib/atmd.h --- old/atm/lib/atmd.h Tue Oct 21 15:54:33 1997 +++ new/atm/lib/atmd.h Fri Feb 27 19:38:40 1998 @@ -1,10 +1,10 @@ /* atmd.h - Functions useful for demons */ -/* Written 1995-1997 by Werner Almesberger, EPFL-LRC */ +/* Written 1995-1998 by Werner Almesberger, EPFL-LRC/ICA */ -#ifndef ATMD_H -#define ATMD_H +#ifndef _ATMD_H +#define _ATMD_H /*--------------------------- Common definitions ----------------------------*/ diff -ur --new-file old/atm/lib/atmres.h new/atm/lib/atmres.h --- old/atm/lib/atmres.h Thu Nov 14 08:06:18 1996 +++ new/atm/lib/atmres.h Fri Feb 27 19:38:50 1998 @@ -1,10 +1,10 @@ /* atmres.h - Common definitions and prototypes for resolver functions */ -/* Written 1996 by Werner Almesberger, EPFL-LRC */ +/* Written 1996,1998 by Werner Almesberger, EPFL-LRC/ICA */ -#ifndef ATMRES_H -#define ATMRES_H +#ifndef _ATMRES_H +#define _ATMRES_H #include #include diff -ur --new-file old/atm/lib/atmsap.h new/atm/lib/atmsap.h --- old/atm/lib/atmsap.h Tue Oct 1 18:33:27 1996 +++ new/atm/lib/atmsap.h Wed Mar 4 08:20:22 1998 @@ -1,11 +1,12 @@ /* atmsap.h - ATM Service Access Point addressing definitions */ -/* Written 1996 by Werner Almesberger, EPFL LRC */ +/* Written 1996-1998 by Werner Almesberger, EPFL LRC/ICA */ #ifndef _ATMSAP_H #define _ATMSAP_H +#include #include @@ -19,6 +20,7 @@ * Selected Organizationally Unique Identifiers (OUIs) */ +#define ATM_FORUM_OUI "\x00\xA0\x3E" /* ATM Forum */ #define EPFL_OUI "\x00\x60\xD7" /* EPF Lausanne, CH */ /* @@ -27,7 +29,17 @@ * bytes assigned by the organization owning the OUI. */ +#define ANS_HLT_VS_ID ATM_FORUM_OUI "\x00\x00\x00\x01" + /* ATM Name System, af-saa-0069.000 */ +#define VOD_HLT_VS_ID ATM_FORUM_OUI "\x00\x00\x00\x02" + /* VoD, af-saa-0049.001 */ #define AREQUIPA_HLT_VS_ID EPFL_OUI "\x01\x00\x00\x01" /* Arequipa */ #define TTCP_HLT_VS_ID EPFL_OUI "\x01\x00\x00\x03" /* ttcp_atm */ + + +/* Mapping of "well-known" TCP, UDP, etc. port numbers to ATM BHLIs. + btd-saa-api-bhli-01.02 */ + +void atm_tcpip_port_mapping(char *vs_id,uint8_t protocol,uint16_t port); #endif diff -ur --new-file old/atm/lib/misc.c new/atm/lib/misc.c --- old/atm/lib/misc.c Wed Nov 5 22:33:38 1997 +++ new/atm/lib/misc.c Wed Mar 4 08:20:51 1998 @@ -1,15 +1,18 @@ /* misc.c - Miscellaneous library functions */ -/* Written 1997 by Werner Almesberger, EPFL-ICA */ +/* Written 1997,1998 by Werner Almesberger, EPFL-ICA */ +#include #include #include #include #include +#include /* for htons */ #include #include +#include int create_leaf(int session) @@ -45,4 +48,13 @@ va_end(ap); if (best > -1) (*pos) += best_len; return best; +} + + +void atm_tcpip_port_mapping(char *vs_id,uint8_t protocol,uint16_t port) +{ + memcpy(vs_id,ATM_FORUM_OUI "\x01",4); + vs_id[4] = protocol; /* e.g. IP_TCP or IP_UDP; from netinet/protocols.h */ + vs_id[5] = (htons(port) >> 8) & 255; + vs_id[6] = htons(port) & 255; } diff -ur --new-file old/atm/lib/sapequal.c new/atm/lib/sapequal.c --- old/atm/lib/sapequal.c Thu Jan 1 01:00:00 1970 +++ new/atm/lib/sapequal.c Thu Mar 5 16:21:10 1998 @@ -0,0 +1,132 @@ +/* sapequal.c - Compares SAP specifications for compatibility */ + +/* Written 1998 by Werner Almesberger, EPFL ICA */ + + +#include +#include + +#include "atm.h" +#include "atmsap.h" + + +static int bhli_compat(const struct atm_bhli a,const struct atm_bhli b) +{ + int length; + + if (a.hl_type != b.hl_type) return 0; + switch (a.hl_type) { + case ATM_HL_ISO: + case ATM_HL_USER: + length = a.hl_length; + if (length != b.hl_length) return 0; + break; + case ATM_HL_HLP: + length = 4; + break; + case ATM_HL_VENDOR: + length = 7; + break; + default: + length = 0; + } + return !length || !memcmp(a.hl_info,b.hl_info,length); +} + + +#define CHECK(FIELD,CONSTRAINT) \ + if (res && !res->FIELD) res->FIELD = a.FIELD; \ + if (a.FIELD && b.FIELD && a.FIELD != b.FIELD) { \ + if (!(flags & SXE_NEGOTIATION)) return 0; \ + if (!CONSTRAINT) return 0; \ + if (res) res->FIELD = a.FIELD < b.FIELD ? a.FIELD : b.FIELD; \ + } + + +static int match_blli(const struct atm_blli a,const struct atm_blli b, + int flags,struct atm_blli *res) +{ + if (res) *res = b; + if (a.l2_proto != b.l2_proto || a.l3_proto != b.l3_proto) return 0; + switch (a.l2_proto) { + case ATM_L2_X25_LL: + case ATM_L2_X25_ML: + case ATM_L2_HDLC_ARM: + case ATM_L2_HDLC_NRM: + case ATM_L2_HDLC_ABM: + case ATM_L2_Q922: + case ATM_L2_ISO7776: + CHECK(l2.itu.mode,1); + CHECK(l2.itu.window,a.l2.itu.window > b.l2.itu.window); + break; + default: + } + switch (a.l3_proto) { + case ATM_L3_X25: + case ATM_L3_ISO8208: + case ATM_L3_X223: + CHECK(l3.itu.mode,1); + CHECK(l3.itu.def_size,a.l3.itu.def_size > b.l3.itu.def_size); + CHECK(l3.itu.window,a.l3.itu.window > b.l3.itu.window); + break; + case ATM_L3_TR9577: + if (a.l3.tr9577.ipi != b.l3.tr9577.ipi) return 0; + if (a.l3.tr9577.ipi == NLPID_IEEE802_1_SNAP) + if (memcmp(a.l3.tr9577.snap,b.l3.tr9577.snap,5)) return 0; + break; + case ATM_L3_USER: + if (a.l3.user != b.l3.user) return 0; + break; + default: + } + return 1; +} + + +#undef CHECK + + +static int blli_compat(const struct atm_blli *a,const struct atm_blli *b, + int flags,struct atm_blli *res) +{ + int i,j; + + if (!(flags & SXE_COMPATIBLE)) { + for (i = 0; i < ATM_MAX_BLLI; i++) + if (blli_in_use(a[i])) + if (!blli_in_use(b[i])) return 0; + else { + if (!match_blli(a[i],b[i],0,NULL)) return 0; + } + else if (blli_in_use(b[i])) return 0; + else break; + if (res) *res = *a; + return 1; + } + if (!blli_in_use(*a)) { + if (res) *res = *b; + return 1; + } + for (i = 0; i < ATM_MAX_BLLI && blli_in_use(a[i]); i++) + for (j = 0; j < ATM_MAX_BLLI && blli_in_use(b[j]); j++) + if (match_blli(a[i],b[j],flags,res)) return 1; + return 0; +} + + +int sap_equal(const struct atm_sap *a,const struct atm_sap *b,int flags,...) +{ + va_list ap; + struct atm_sap *res; + + va_start(ap,flags); + res = flags & SXE_RESULT ? va_arg(ap,struct atm_sap *) : NULL; + va_end(ap); + if (!bhli_compat(a->bhli,b->bhli)) return 0; + if (!blli_compat(a->blli,b->blli,flags,res ? res->blli : NULL)) return 0; + if (res) { + res->bhli = a->bhli; + memset(res->blli+1,0,sizeof(struct atm_blli)*2); + } + return 1; +} diff -ur --new-file old/atm/lib/stdint.h new/atm/lib/stdint.h --- old/atm/lib/stdint.h Thu Jan 1 01:00:00 1970 +++ new/atm/lib/stdint.h Fri Feb 27 19:59:03 1998 @@ -0,0 +1,12 @@ +/* stdint.h - provides uintXX_t until glibc does */ + +#ifndef _STDINT_H +#define _STDINT_H + +/* Works for i386 and Alpha */ + +typedef unsigned char uint8_t; +typedef unsigned short uint16_t; +typedef unsigned int uint32_t; + +#endif diff -ur --new-file old/atm/maint/atmtcp.c new/atm/maint/atmtcp.c --- old/atm/maint/atmtcp.c Mon Nov 3 17:50:09 1997 +++ new/atm/maint/atmtcp.c Wed Mar 4 08:24:02 1998 @@ -1,11 +1,12 @@ /* atmtcp.c - control ATM on TCP emulation */ -/* Written 1995,1997 by Werner Almesberger, EPFL-LRC */ +/* Written 1995-1998 by Werner Almesberger, EPFL-LRC/ICA */ #include #include #include +#include #include #include #include @@ -62,8 +63,8 @@ bytes += ret; if (bytes < sizeof(struct atmtcp_hdr)) return; if (ntohl(((struct atmtcp_hdr *) buf)->length) > ATM_MAX_AAL5_PDU) { - fprintf(stderr,"giant PDU (length = %ld) received\n", - ntohl(((struct atmtcp_hdr *) buf)->length)); + fprintf(stderr,"giant PDU (length = %d) received\n", + (unsigned int) ntohl(((struct atmtcp_hdr *) buf)->length)); exit(1); } if (bytes < sizeof(struct atmtcp_hdr)+ diff -ur --new-file old/atm/mkdist new/atm/mkdist --- old/atm/mkdist Wed Nov 19 03:57:41 1997 +++ new/atm/mkdist Thu Mar 12 17:36:51 1998 @@ -1,7 +1,7 @@ #!/bin/sh [ -r ./VERSION ] || exit 1 VERSION=`cat ./VERSION` -SRCDIR=$HOME/k/2137 +SRCDIR=$HOME/k/2179 ARCHDIR=$HOME/l/arch ( cd $SRCDIR @@ -15,7 +15,7 @@ atm/WARNING \ atm/VERSION atm/README atm/README.DRIVERS atm/CREDITS atm/USAGE \ atm/CHANGES atm/BUGS \ - atm/COPYING atm/COPYING.GPL \ + atm/COPYING atm/COPYING.GPL atm/COPYING.LGPL \ atm/Makefile atm/Rules.make atm/mkdist atm/mkdiff atm/mkbindist \ atm/.kernel \ atm/doc/README atm/doc/usage.tex atm/doc/usage.txt atm/doc/url.sty \ @@ -68,22 +68,23 @@ atm/test/Makefile atm/test/aread.c atm/test/awrite.c atm/test/br.c \ atm/test/bw.c atm/test/ttcp.c atm/test/aping.c atm/test/window.c \ atm/test/align.c atm/test/isp.c atm/test/isp.h atm/test/ispl.l \ - atm/test/ispl.y atm/test/mkerrnos.pl \ + atm/test/ispl.y atm/test/mkerrnos.pl atm/test/README.isp \ atm/ip/Makefile atm/ip/atmarp.c atm/ip/clip.c atm/ip/clip.8 atm/ip/atmarp.8 \ atm/debug/Makefile atm/debug/ed.c atm/debug/encopy.c atm/debug/endump.c \ atm/debug/peek.pl atm/debug/zndump.c atm/debug/znth.c atm/debug/delay.c \ - atm/debug/aqtest.c \ + atm/debug/aqtest.c atm/debug/svctor.c \ atm/lib/Makefile atm/lib/atm2text.c atm/lib/atm.h atm/lib/text2atm.c \ atm/lib/atmequal.c atm/lib/sdu2cell.c atm/lib/atmsap.h \ atm/lib/atmd.h atm/lib/common.c atm/lib/diag.c \ atm/lib/timer.c atm/lib/arequipa.h atm/lib/arequipa.c \ atm/lib/text2qos.c atm/lib/qos2text.c atm/lib/qosequal.c \ - atm/lib/sap2text.c atm/lib/text2sap.c atm/lib/misc.c \ + atm/lib/sap2text.c atm/lib/text2sap.c atm/lib/sapequal.c atm/lib/misc.c \ atm/lib/atmres.h atm/lib/ans.c atm/lib/rtf2e164_cc.pl \ + atm/lib/stdint.h \ atm/led/USAGE atm/led/COPYRIGHT.DEC atm/led/COPYRIGHT.TUT \ atm/led/lec.h atm/led/lec_arp.h atm/led/lec_ctrl.h atm/led/emask.h \ atm/led/le_disp.h atm/led/g_event.h \ - atm/led/addr_reg.h atm/led/af_lane.h atm/led/atm.h atm/led/cm.h \ + atm/led/addr_reg.h atm/led/af_lane.h atm/led/lane_atm.h atm/led/cm.h \ atm/led/cm_sap.h atm/led/codes.h atm/led/g_endian.h atm/led/g_types.h \ atm/led/svc_info.h atm/led/system.h \ atm/led/utl.h atm/led/utl_os.h atm/led/timers.h atm/led/kernel_itf.h \ diff -ur --new-file old/atm/qgen/msg.fmt new/atm/qgen/msg.fmt --- old/atm/qgen/msg.fmt Thu Nov 6 03:40:52 1997 +++ new/atm/qgen/msg.fmt Wed Feb 18 15:27:09 1998 @@ -1,6 +1,6 @@ /* msg.fmt - Signaling message format decription for UNI 3.0, 3.1, and 4.0 */ -/* Written 1995-1997 by Werner Almesberger, EPFL-LRC */ +/* Written 1995-1998 by Werner Almesberger, EPFL-LRC */ #undef linux /* grr ... */ @@ -135,10 +135,10 @@ # Note: cannot use ATM_HL_* here, because those values are incremented by one # to keep zero available for ATM_HL_NONE 0 { # ISO - iso_hli <-64> + iso_hli <-72> } 1 { # User Specific - user_hli <-64> + user_hli <-72> } #if defined(UNI30) || defined(ALLOW_UNI30) 2 { # High layer profile - UNI 3.0 only diff -ur --new-file old/atm/saal/pdu.c new/atm/saal/pdu.c --- old/atm/saal/pdu.c Tue Oct 21 16:06:18 1997 +++ new/atm/saal/pdu.c Fri Feb 27 19:36:10 1998 @@ -1,8 +1,9 @@ /* pdu.c - SSCOP (Q.2110) PDU reader */ -/* Written 1995-1997 by Werner Almesberger, EPFL-LRC */ +/* Written 1995-1998 by Werner Almesberger, EPFL-LRC/ICA */ +#include #include /* for ntohl */ #include "pdu.h" @@ -109,7 +110,7 @@ int decompose_pdu(void *maa_arg,void *msg,int size,unsigned char *type, int *length,int *s,int *ps,int *r,int *mr,int *sq) { - __u32 *last; + uint32_t *last; unsigned char pad; int n; @@ -123,7 +124,7 @@ if (pdu_maa) pdu_maa(maa_arg,'U',0); return -1; } - last = (__u32 *) ((char *) msg+size-4); + last = (uint32_t *) ((char *) msg+size-4); *type = SSCOP_TYPE(*last); pad = SSCOP_PAD(*last); n = SSCOP_N(*last); @@ -140,7 +141,7 @@ return -1; } *s = n; - *ps = SSCOP_N(*(__u32 *) msg); + *ps = SSCOP_N(*(uint32_t *) msg); break; case SSCOP_STAT: if (size < 12) { diff -ur --new-file old/atm/saal/pdu.h new/atm/saal/pdu.h --- old/atm/saal/pdu.h Tue Oct 21 16:06:06 1997 +++ new/atm/saal/pdu.h Fri Feb 27 19:36:20 1998 @@ -1,11 +1,14 @@ /* pdu.h - SSCOP (Q.2110) PDU reader */ -/* Written 1995-1997 by Werner Almesberger, EPFL-LRC */ +/* Written 1995-1998 by Werner Almesberger, EPFL-LRC/ICA */ #ifndef PDU_H #define PDU_H +#include + + /* SSCOP PDU types, Q.2110 section 7.1 */ #define SSCOP_BGN 1 /* Request Initialization */ @@ -38,7 +41,7 @@ /* Work around a buggy ntohl prototype in some early version of glibc on 64 bit platforms. */ -#define _ntohl(l) (ntohl((__u32) (l)) & 0xffffffffU) +#define _ntohl(l) (ntohl((uint32_t) (l)) & 0xffffffffU) extern const char *pdu_name[]; diff -ur --new-file old/atm/saal/sscop.c new/atm/saal/sscop.c --- old/atm/saal/sscop.c Tue Oct 21 16:11:44 1997 +++ new/atm/saal/sscop.c Wed Mar 4 16:40:59 1998 @@ -1,9 +1,10 @@ /* sscop.c - SSCOP (Q.2110) protocol */ -/* Written 1995-1997 by Werner Almesberger, EPFL-LRC */ +/* Written 1995-1998 by Werner Almesberger, EPFL-LRC/ICA */ #include +#include #include #include #include /* for htonl */ @@ -141,7 +142,7 @@ static int sdu_length(BUFFER *buf) { - return buf->length-4-SSCOP_PAD(*(__u32 *) ((char *) buf->data+ + return buf->length-4-SSCOP_PAD(*(uint32_t *) ((char *) buf->data+ buf->length-4)); } @@ -150,7 +151,7 @@ int num) { BUFFER *buf; - __u32 *trailer; + uint32_t *trailer; int pad; buf = buffer_create(num+12,dsc->vt_s); /* space for trailers */ @@ -158,11 +159,11 @@ memset((char *) buf->data+(num & ~3),0,4); /* clear padding area */ memcpy((unsigned char *) buf->data,data,num); pad = (4-(num & 3)) & 3; - trailer = (__u32 *) ((char *) buf->data+num+pad); + trailer = (uint32_t *) ((char *) buf->data+num+pad); } else { pad = 0; - trailer = (__u32 *) buf->data; + trailer = (uint32_t *) buf->data; } diag(COMPONENT,DIAG_DEBUG,"generating %s PDU",pdu_name[type]); switch (type) { @@ -227,7 +228,7 @@ } if (dsc->ops->cpcs_send) dsc->ops->cpcs_send(dsc->user,buf->data,buf->length); - switch (SSCOP_TYPE(*(__u32 *) ((char *) buf->data+buf->length-4))) { + switch (SSCOP_TYPE(*(uint32_t *) ((char *) buf->data+buf->length-4))) { case SSCOP_BGN: last = &dsc->last_bgn; break; @@ -286,7 +287,7 @@ static void send_ustat(SSCOP_DSC *dsc,int first,int last) { - __u32 range[2]; + uint32_t range[2]; range[0] = htonl(first); range[1] = htonl(last); @@ -710,7 +711,7 @@ { int curr,i; - if (!dsc->list) dsc->list = alloc(dsc->cf_max_stat*sizeof(__u32)); + if (!dsc->list) dsc->list = alloc(dsc->cf_max_stat*sizeof(uint32_t)); if (NORM_RX(dsc->vr_h) > NORM_RX(s)) { start_error_recov(dsc,'Q'); return; @@ -779,11 +780,11 @@ } -static void data_stat(SSCOP_DSC *dsc,int ps,int mr,int r,__u32 *list, +static void data_stat(SSCOP_DSC *dsc,int ps,int mr,int r,uint32_t *list, int length) /* 20.44-46 */ { BUFFER *buf,*buf2; - __u32 *curr,tmp; + uint32_t *curr,tmp; int i,count,seq1,seq2; if (NEGATIVE(NORM_TXP(ps)) || NORM_TXP(ps) > NORM_TXP(dsc->vt_ps)) { @@ -1430,8 +1431,8 @@ data_poll(dsc,s); return 1; case SSCOP_USTAT: - data_ustat(dsc,mr,r,SSCOP_N(((__u32 *) msg)[0]), - SSCOP_N(((__u32 *) msg)[1])); + data_ustat(dsc,mr,r,SSCOP_N(((uint32_t *) msg)[0]), + SSCOP_N(((uint32_t *) msg)[1])); return 1; case SSCOP_STAT: data_stat(dsc,ps,mr,r,msg,length/4); diff -ur --new-file old/atm/saal/sscop.h new/atm/saal/sscop.h --- old/atm/saal/sscop.h Mon Oct 6 20:22:16 1997 +++ new/atm/saal/sscop.h Fri Feb 27 19:36:47 1998 @@ -1,11 +1,13 @@ /* sscop.h - SSCOP (Q.2110) user interface */ -/* Written 1995-1997 by Werner Almesberger, EPFL-LRC */ +/* Written 1995-1998 by Werner Almesberger, EPFL-LRC/ICA */ #ifndef SSCOP_H #define SSCOP_H +#include + #include "atmd.h" #include "queue.h" @@ -47,7 +49,7 @@ QUEUE tx_buf,tx_q,rx_buf,rt_q; BUFFER *last_bgn,*last_end,*last_rs,*last_er; /* for retransmission */ /* Misc items */ - __u32 *list; /* STAT construction list */ + uint32_t *list; /* STAT construction list */ } SSCOP_DSC; diff -ur --new-file old/atm/sigd/atmsigd.c new/atm/sigd/atmsigd.c --- old/atm/sigd/atmsigd.c Wed Nov 5 00:22:23 1997 +++ new/atm/sigd/atmsigd.c Thu Feb 12 12:20:01 1998 @@ -1,6 +1,6 @@ /* atmsigd.c - ATM signaling demon */ -/* Written 1995-1997 by Werner Almesberger, EPFL-LRC */ +/* Written 1995-1998 by Werner Almesberger, EPFL-LRC/ICA */ #include @@ -31,6 +31,7 @@ extern FILE *yyin; int net = 0; +int allocate_ci = 1; int debug = 0; int pretty = A2T_PRETTY | A2T_NAME | A2T_LOCAL; int sig_pcr = -1; /* obsolete */ @@ -282,7 +283,7 @@ { fprintf(stderr,"usage: %s [ -b ] [ -c config_file ] [ -d ] " "[ -D dump_dir ]\n" - " [ -l logfile ] [ -n ] [ -N ] [ -q qos ] [ -t trace_length ]\n" + " [ -l logfile ] [ -n ] [ -N [ -A ] ] [ -q qos ] [ -t trace_length ]\n" " [ [itf.]vpi.vci [ input output ] ]\n",name); exit(1); } @@ -301,7 +302,7 @@ memset(&signaling_pvc,0,sizeof(signaling_pvc)); signaling_pvc.sap_addr.vci = 5; /* 1st pass to get the -c option */ - while ((c = getopt(argc,argv,"bc:dD:l:nNP:q:t:")) != EOF) + while ((c = getopt(argc,argv,"Abc:dD:l:nNP:q:t:")) != EOF) if (c == 'c') config_file = optarg; if (!(yyin = fopen(config_file,"r"))) diag(COMPONENT,DIAG_WARN,"%s not found. - Using defaults.",config_file); @@ -311,8 +312,11 @@ } /* process all other options but -c */ optind = 0; - while ((c = getopt(argc,argv,"bc:dD:l:nNP:q:t:")) != EOF) + while ((c = getopt(argc,argv,"Abc:dD:l:nNP:q:t:")) != EOF) switch (c) { + case 'A': + allocate_ci = 0; + break; case 'b': background = 1; break; @@ -355,6 +359,7 @@ default: usage(argv[0]); } + if (!allocate_ci && !net) usage(argv[0]); if (optind < argc) { if (text2atm(argv[optind],(struct sockaddr *) &signaling_pvc, sizeof(signaling_pvc),T2A_PVC) < 0) diff -ur --new-file old/atm/sigd/atmsigd.conf.4 new/atm/sigd/atmsigd.conf.4 --- old/atm/sigd/atmsigd.conf.4 Mon Nov 3 22:41:19 1997 +++ new/atm/sigd/atmsigd.conf.4 Thu Mar 5 22:58:37 1998 @@ -1,4 +1,4 @@ -.TH ATMSIGD.CONF 4 "Nov 3, 1997" "Linux" "File Formats" +.TH ATMSIGD.CONF 4 "Mar 5, 1998" "Linux" "File Formats" .SH NAME atmsigd.conf \- configuration file for the ATM signaling demon .SH SYNOPSIS @@ -25,7 +25,8 @@ .IP \fBdebug\ level\ \fIlevel\fP Sets the default debug level to \fIlevel\fP. \fIlevel\fP can be any of \fBdebug\fP, \fBinfo\fP, \fBwarn\fP, \fBerror\fP, and \fBfatal\fP. Only -messages with a higher priority than the debug level are printed. Note that +messages with the same or a higher priority than the debug level are printed. +Note that the command-line option \fB\-d\fP generates even more output (e.g. hexdumps of all packets passing between \fBatmsigd\fP and the network) than \fBdebug level debug\fP. diff -ur --new-file old/atm/sigd/kernel.c new/atm/sigd/kernel.c --- old/atm/sigd/kernel.c Wed Nov 19 03:05:52 1997 +++ new/atm/sigd/kernel.c Fri Mar 13 20:29:20 1998 @@ -1,10 +1,11 @@ /* kernel.c - Processing of incoming kernel messages */ -/* Written 1995-1997 by Werner Almesberger, EPFL-LRC */ +/* Written 1995-1998 by Werner Almesberger, EPFL-LRC/ICA */ #include #include +#include #include #include #include @@ -82,18 +83,22 @@ q_write(&dsc,QF_cgpn,(void *) local->sas_addr.prv,ATM_ESA_LEN); } if (net) { - int vci; + if (!atmpvc_addr_in_use(sock->pvc)) { + int vci; - vci = get_vci(0); - if (vci < 0) { - (void) q_close(&dsc); - return vci; + if (!allocate_ci) + diag(COMPONENT,DIAG_FATAL,"No CI allocator (use -A)"); + vci = get_vci(0); + if (vci < 0) { + (void) q_close(&dsc); + return vci; + } + sock->pvc.sap_addr.itf = get_itf(0); + sock->pvc.sap_addr.vpi = 0; + sock->pvc.sap_addr.vci = vci; } - q_assign(&dsc,QF_vpi,0); /* @@@ */ - q_assign(&dsc,QF_vci,vci); - sock->pvc.sap_addr.itf = get_itf(0); - sock->pvc.sap_addr.vpi = 0; - sock->pvc.sap_addr.vci = vci; + q_assign(&dsc,QF_vpi,sock->pvc.sap_addr.vpi); + q_assign(&dsc,QF_vci,sock->pvc.sap_addr.vci); } if ((size = q_close(&dsc)) < 0) error = -EINVAL; else if (!error) to_signaling(q_buffer,size); @@ -228,6 +233,7 @@ sock->qos = msg->qos; sock->sap = msg->sap; sock->state = ss_connecting; + sock->pvc = msg->pvc; error = send_setup(sock); if (error) { SEND_ERROR(msg->vcc,error); @@ -239,11 +245,14 @@ return; case as_accept: if (sock->state == ss_zombie) { - SEND_ERROR(msg->vcc,-ECONNRESET); /* -ERESTARTSYS ? */ + SEND_ERROR(msg->vcc,-ECONNABORTED); /* -ERESTARTSYS ? */ free_sock(sock); return; } - if (sock->state != ss_indicated) break; + if (sock->state != ss_indicated && sock->state != ss_proceeding) + break; + if (sock->state == ss_indicated && net) + diag(COMPONENT,DIAG_FATAL,"No CI allocator (use -A)"); error = send_connect(sock); if (!error) { START_TIMER(sock,T313); @@ -255,16 +264,24 @@ START_TIMER(sock,T308_1); new_state(sock,ss_wait_rel); return; - case as_reject: /* ZOMBIE or INDICATED */ - if (sock->state == ss_zombie) { - free_sock(sock); - return; + case as_reject: /* ZOMBIE, INDICATED, or PROCEEDING */ + switch (sock->state) { + case ss_indicated: + send_release_complete(sock->call_ref,ATM_CV_CALL_REJ); + /* fall through */ + case ss_zombie: + free_sock(sock); + return; + case ss_proceeding: + send_release(sock,ATM_CV_CALL_REJ); + /* @@@ should use msg->reply */ + START_TIMER(sock,T308_1); + new_state(sock,ss_wait_rel); + return; + default: + break; } - if (sock->state != ss_indicated) break; - send_release(sock,ATM_CV_CALL_REJ); /* @@@ should use msg->reply */ - START_TIMER(sock,T308_1); - new_state(sock,ss_wait_rel); - return; + break; case as_listen: /* NULL */ if (sock) break; if (msg->svc.sas_family != AF_ATMSVC) { @@ -286,11 +303,16 @@ send_kernel(sock->id,0,as_okay,0,NULL,NULL,NULL,NULL,NULL); sock->state = ss_listening; return; - case as_close: /* all but INDICATED, ZOMBIE, and WAIT_REL */ - if (sock && (sock->state == ss_indicated || sock->state == - ss_zombie || sock->state == ss_wait_rel)) break; + case as_close: /* all but INDICATED, PROCEEDING, ZOMBIE, and WAIT_REL */ + if (sock && (sock->state == ss_indicated || + sock->state == ss_proceeding || sock->state == ss_zombie || + sock->state == ss_wait_rel)) break; switch (sock ? sock->state : ss_null) { case ss_listening: + send_close(sock); + if (sock->listen) new_state(sock,ss_listen_zombie); + else free_sock(sock); + return; case ss_zombie: send_close(sock); /* fall through */ @@ -340,6 +362,23 @@ break; } break; + case as_identify: + if (sock->state != ss_indicated && sock->state != ss_proceeding) + break; + if (!atmpvc_addr_in_use(msg->pvc)) { + if (net && !allocate_ci) + diag(COMPONENT,DIAG_FATAL,"No CI allocator (use -A)"); + return; + } + if (net && allocate_ci) { + diag(COMPONENT,DIAG_FATAL,"CI allocation role conflict"); + return; + } + sock->pvc = msg->pvc; + if (send_call_proceeding(sock)) + diag(COMPONENT,DIAG_FATAL,"s_c_p failed"); + new_state(sock,ss_proceeding); + return; #ifdef Q2963_1 case as_modify: if (sock && (sock->state == ss_mod_lcl || @@ -449,10 +488,12 @@ } if (!(next = sock->listen)) { diag(COMPONENT,DIAG_WARN, - "socket 0x%lx got accept with empty listen queue",msg->vcc); + "socket 0x%lx got accept/reject/identify with empty listen queue", + msg->vcc); return; } sock->listen = next->listen; + if (sock->state == ss_listen_zombie && !sock->listen) free_sock(sock); next->listen = NULL; next->id = msg->vcc; dispatch(next,msg); @@ -497,16 +538,18 @@ itf_load(msg->pvc.sap_addr.itf); return; } - if (msg->type != as_accept && msg->type != as_reject) { - dispatcher = dispatch; + if (msg->listen_vcc && (msg->type == as_accept || msg->type == as_reject || + msg->type == as_identify)) { + dispatcher = dispatch_listen; for (curr = sockets; curr; curr = curr->next) - if (msg->vcc == curr->id) break; + if (msg->listen_vcc == curr->id && (curr->state == ss_listening || + curr->state == ss_listen_zombie)) + break; } else { - dispatcher = dispatch_listen; + dispatcher = dispatch; for (curr = sockets; curr; curr = curr->next) - if (msg->listen_vcc == curr->id && curr->state == ss_listening) - break; + if (msg->vcc == curr->id) break; } diag(COMPONENT,DIAG_DEBUG,"FROM KERNEL: %s for socket %p (0x%lx/0x%lx) " "in state %s",as_name[msg->type],curr,msg->vcc,msg->listen_vcc, diff -ur --new-file old/atm/sigd/proto.c new/atm/sigd/proto.c --- old/atm/sigd/proto.c Thu Nov 6 02:56:14 1997 +++ new/atm/sigd/proto.c Fri Mar 13 20:23:31 1998 @@ -1,6 +1,6 @@ /* proto.c - Common protocol functions and structures */ -/* Written 1995-1997 by Werner Almesberger, EPFL-LRC */ +/* Written 1995-1998 by Werner Almesberger, EPFL-LRC */ #include @@ -26,6 +26,7 @@ "", "ss_null", "ss_listening", "ss_connecting", "ss_connected", "ss_indicated", "ss_accepting", "ss_zombie", "ss_wait_rel", "ss_wait_close","ss_rel_req", "ss_rel_ind", + "ss_proceeding","ss_listen_zombie", "ss_mod_lcl", "ss_mod_req", "ss_mod_rcv", "ss_mod_fin_ack", "ss_mod_fin_ok","ss_mod_fin_fail" }; @@ -38,12 +39,13 @@ const char *as_name[] = { "","as_bind","as_connect","as_accept", "as_reject","as_listen","as_okay","as_error","as_indicate","as_close", - "as_itf_notify","as_modify" }; + "as_itf_notify","as_modify","as_identify" }; const CALL_STATE state_map[] = { /* formatting aligned with STATE */ cs_null, cs_null, cs_null, cs_call_init, cs_active, cs_in_proc, cs_conn_req, cs_null, cs_rel_req, cs_null, cs_rel_req, cs_rel_ind, + cs_in_proc, cs_null, #ifdef Q2963_1 cs_active, cs_mod_req, cs_mod_rcv, cs_active, cs_active, cs_active @@ -286,7 +288,7 @@ void send_close(SOCKET *sock) { - if (sock->error == 1234) diag(COMPONENT,DIAG_ERROR,"BUG! BUG! BUG!"); + if (sock->error == 1234) diag(COMPONENT,DIAG_FATAL,"BUG! BUG! BUG!"); send_kernel(sock->id,0L,as_close,sock->error,NULL,NULL,NULL,NULL,NULL); sock->error = 1234; } diff -ur --new-file old/atm/sigd/proto.h new/atm/sigd/proto.h --- old/atm/sigd/proto.h Wed Nov 5 19:56:08 1997 +++ new/atm/sigd/proto.h Fri Mar 13 20:23:37 1998 @@ -1,6 +1,6 @@ /* proto.h - Common protocol functions and structures */ -/* Written 1995-1997 by Werner Almesberger, EPFL-LRC */ +/* Written 1995-1998 by Werner Almesberger, EPFL-LRC */ #ifndef PROTO_H @@ -16,6 +16,7 @@ ss_invalid, ss_null, ss_listening, ss_connecting, ss_connected, ss_indicated, ss_accepting, ss_zombie, ss_wait_rel, ss_wait_close, ss_rel_req, ss_rel_ind, + ss_proceeding, ss_listen_zombie, #ifdef Q2963_1 ss_mod_lcl, ss_mod_req, ss_mod_rcv, ss_mod_fin_ack, ss_mod_fin_ok, ss_mod_fin_fail @@ -73,6 +74,7 @@ #define DEFAULT_TRACE_SIZE 20 extern int net; +extern int allocate_ci; extern int pretty; extern int sig_pcr; extern const char *sig_qos; @@ -109,6 +111,7 @@ void send_release(SOCKET *sock,unsigned char reason,...); void send_release_complete(unsigned long call_ref,unsigned char cause); +int send_call_proceeding(SOCKET *sock); void send_modify_reject(SOCKET *sock,unsigned char reason); const char *mid2name(unsigned char mid); diff -ur --new-file old/atm/sigd/sap.c new/atm/sigd/sap.c --- old/atm/sigd/sap.c Thu Nov 6 03:00:10 1997 +++ new/atm/sigd/sap.c Thu Mar 5 16:24:25 1998 @@ -1,10 +1,11 @@ /* sap.c - SAP manipulations */ -/* Written 1996,1997 by Werner Almesberger, EPFL-LRC */ +/* Written 1996-1998 by Werner Almesberger, EPFL-LRC/ICA */ #include #include +#include #include #include #include @@ -46,69 +47,6 @@ } -static int bhli_compat(const struct atm_bhli *old,const struct atm_bhli *new, - struct atm_bhli *res) -{ - int length; - - if (res) *res = *new; -/* if (!old->hl_type) return 1; --- GONE */ - if (old->hl_type != new->hl_type) return 0; - switch (old->hl_type) { - case ATM_HL_ISO: - case ATM_HL_USER: - length = old->hl_length; - if (length != new->hl_length) return 0; - break; -#ifdef UNI30 - case ATM_HL_HLP: - length = 4; - break; -#endif - case ATM_HL_VENDOR: - length = 7; - break; - default: - length = 0; - } - return !length || !memcmp(old->hl_info,new->hl_info,length); -} - - -static int match_blli(const struct atm_blli *a,const struct atm_blli *b) -{ - if (a->l2_proto != b->l2_proto || a->l3_proto != b->l3_proto) return 0; - switch (a->l3_proto) { - case ATM_L3_TR9577: - if (a->l3.tr9577.ipi != b->l3.tr9577.ipi) return 0; - if (a->l3.tr9577.ipi == NLPID_IEEE802_1_SNAP) - if (memcmp(a->l3.tr9577.snap,b->l3.tr9577.snap,5)) return 0; - break; - case ATM_L3_USER: - if (a->l3.user != b->l3.user) return 0; - break; - default: - } - return 1; -} - - -static int blli_compat(const struct atm_blli *old,const struct atm_blli *new, - struct atm_blli *res) -{ - int i,j; - - if (!blli_in_use(*old)) return 1; - for (i = 0; i < ATM_MAX_BLLI && blli_in_use(old[i]); i++) - for (j = 0; j < ATM_MAX_BLLI && blli_in_use(new[j]); j++) - if (match_blli(old+i,new+j)) { - if (res) *res = new[j]; - return 1; - } - return 0; -} - - int sap_compat(const struct sockaddr_atmsvc *old_addr, const struct sockaddr_atmsvc *new_addr,struct sockaddr_atmsvc *res_addr, const struct atm_sap *old_sap,const struct atm_sap *new_sap, @@ -124,12 +62,9 @@ new_qos->txtp.max_sdu > old_qos->rxtp.max_sdu) return 0; if (!class_compat(&old_qos->txtp,&new_qos->rxtp) || !class_compat(&new_qos->txtp,&old_qos->rxtp)) return 0; - if (res_sap) *res_sap = *new_sap; - if (!bhli_compat(&old_sap->bhli,&new_sap->bhli,res_sap ? &res_sap->bhli : - NULL)) return 0; - if (!blli_compat(old_sap->blli,new_sap->blli,res_sap ? res_sap->blli : - NULL)) return 0; - if (res_sap) memset(res_sap->blli+1,0,sizeof(struct atm_blli)*2); + if (!sap_equal(old_sap,new_sap, + SXE_COMPATIBLE | SXE_NEGOTIATION | (res_sap ? SXE_RESULT : 0),res_sap)) + return 0; return 1; } diff -ur --new-file old/atm/sigd/trace.c new/atm/sigd/trace.c --- old/atm/sigd/trace.c Wed Nov 5 03:07:26 1997 +++ new/atm/sigd/trace.c Wed Mar 4 11:02:15 1998 @@ -1,6 +1,6 @@ /* trace.c - Support functions for message tracing */ -/* Written 1996,1997 by Werner Almesberger, EPFL-LRC */ +/* Written 1996-1998 by Werner Almesberger, EPFL-LRC/ICA */ #include @@ -138,18 +138,10 @@ static void qd_vdump(const char *msg,va_list ap) { - const char *prev,*end; - if (new_line) append(" "); - prev = string; vappend(msg,ap); - if (!prev) prev = string; - if (!prev) new_line = 1; - else { - if (!(end = strrchr(prev,'\n'))) end = prev; - else end++; - new_line = !*end; - } + if (string && curr_len) new_line = string[curr_len-1] == '\n'; + else new_line = 1; } @@ -188,7 +180,7 @@ { static const char *type[] = { "as_catch_null","as_bind","as_connect", "as_accept","as_reject","as_listen","as_okay","as_error","as_indicate", - "as_close","as_itf_notify" }; + "as_close","as_itf_notify","as_modify","as_identify" }; struct atmsvc_msg *m = msg; append(" %s (vcc 0x%x, listen_vcc 0x%x)\n",m->type < sizeof(type)/ @@ -283,11 +275,11 @@ if (string) { free(string); string = NULL; - new_line = 1; } for (walk = first; walk; walk = walk->next) { append("%6d (%d.%06d) %s:\n",walk->number,walk->time.tv_sec, walk->time.tv_usec,walk->comment); + new_line = 1; walk->print(walk->msg,walk->size); } return string; diff -ur --new-file old/atm/sigd/uni.c new/atm/sigd/uni.c --- old/atm/sigd/uni.c Wed Nov 19 03:06:42 1997 +++ new/atm/sigd/uni.c Fri Mar 13 21:11:54 1998 @@ -1,12 +1,13 @@ /* uni.c - Processing of incoming UNI signaling messages */ -/* Written 1995-1997 by Werner Almesberger, EPFL-LRC */ +/* Written 1995-1998 by Werner Almesberger, EPFL-LRC/ICA */ #include #include #include #include +#include #include #include @@ -23,9 +24,6 @@ #include "timeout.h" #include "trace.h" -#define __KERNEL__ /* since that's what we effectively are */ -#include - #define COMPONENT "UNI" @@ -37,7 +35,7 @@ static TIMER *t309 = NULL; -static int send_call_proceeding(SOCKET *sock) +int send_call_proceeding(SOCKET *sock) { Q_DSC dsc; int size; @@ -45,7 +43,7 @@ q_create(&dsc,q_buffer,MAX_Q_MSG); q_assign(&dsc,QF_msg_type,ATM_MSG_CALL_PROC); q_assign(&dsc,QF_call_ref,sock->call_ref); - if (net) { + if (net && allocate_ci) { int vci; vci = get_vci(0); @@ -53,12 +51,14 @@ (void) q_close(&dsc); return vci; } - q_assign(&dsc,QF_vpi,0); /* @@@ */ - q_assign(&dsc,QF_vci,vci); sock->pvc.sap_addr.itf = signaling_pvc.sap_addr.itf; sock->pvc.sap_addr.vpi = 0; sock->pvc.sap_addr.vci = vci; } + if (net) { + q_assign(&dsc,QF_vpi,sock->pvc.sap_addr.vpi); + q_assign(&dsc,QF_vci,sock->pvc.sap_addr.vci); + } if (sock->ep_ref >= 0) q_assign(&dsc,QF_ep_ref,sock->ep_ref); if ((size = q_close(&dsc)) >= 0) to_signaling(q_buffer,size); return 0; @@ -91,7 +91,7 @@ return; } this->qos.aal = ATM_AAL5; /* hack @@@ */ - this->state = ss_indicated; + this->state = net && allocate_ci ? ss_proceeding : ss_indicated; this->call_state = cs_in_proc; this->call_ref = call_ref; if (q_present(&in_dsc,QF_ep_ref)) @@ -99,7 +99,7 @@ #ifdef CISCO else #endif - { + if (net && allocate_ci) { int error; error = send_call_proceeding(this); @@ -148,7 +148,7 @@ diag(COMPONENT,DIAG_DEBUG,"Incoming call from %s",buffer); } } - send_kernel(0,sock->id,as_indicate,0,&this->pvc,&this->remote,NULL, + send_kernel(0,sock->id,as_indicate,0,&this->pvc,&this->remote,&in_addr, &this->sap,&this->qos); for (walk = &sock->listen; *walk; walk = &(*walk)->listen); *walk = this; @@ -400,7 +400,10 @@ case ss_accepting: set_error(sock,-ECONNRESET); /* ERESTARTSYS ? */ send_release_complete(sock->call_ref,0); - /* fall through */ + SEND_ERROR(sock->id,sock->error); + STOP_TIMER(sock); + free_sock(sock); + return; case ss_rel_req: send_close(sock); /* fall through */ @@ -431,11 +434,12 @@ new_state(sock,ss_rel_ind); return; case ss_indicated: + /* fall through */ + case ss_proceeding: send_release_complete(sock->call_ref,0); new_state(sock,ss_zombie); /* fall through */ case ss_rel_ind: - /* send_release_complete(sock->call_ref,0); */ return; default: send_release_complete(sock->call_ref,0); /* @@@ should @@ -473,7 +477,10 @@ /* fall through */ case ss_accepting: set_error(sock,-ECONNRESET); /* ERESTARTSYS ? */ - /* fall through */ + SEND_ERROR(sock->id,sock->error); + STOP_TIMER(sock); + free_sock(sock); + return; case ss_rel_req: send_close(sock); /* fall through */ @@ -506,6 +513,8 @@ new_state(sock,ss_wait_close); return; case ss_indicated: + /* fall through */ + case ss_proceeding: new_state(sock,ss_zombie); return; default: @@ -713,14 +722,19 @@ } -static void abort_call(void) +static void abort_call(unsigned char *msg,int size) { SOCKET *curr; unsigned long call_ref; - diag(COMPONENT,DIAG_ERROR,"can't parse message - aborting the call"); - call_ref = q_fetch(&in_dsc,QF_call_ref)^0x800000; - /* hope that at least the call ref was okay ... */ + if (size < 6) { + diag(COMPONENT,DIAG_ERROR,"message too short (%d bytes)",size); + return; + } + /* hope that at least the call ref is okay ... */ + call_ref = ((msg[3] << 16) | (msg[4] << 8) | msg[5])^0x800000; + diag(COMPONENT,DIAG_ERROR,"can't parse message - aborting the call " + "(CR 0x%06lx)",call_ref); for (curr = sockets; curr; curr = curr->next) if (curr->call_ref == call_ref) { uni_call(curr,ATM_MSG_RESTART); @@ -733,7 +747,7 @@ void to_uni(void *msg,int size) { if (q_open(&in_dsc,msg,size) < 0) { - abort_call(); + abort_call(msg,size); return; } process_uni(msg); diff -ur --new-file old/atm/test/Makefile new/atm/test/Makefile --- old/atm/test/Makefile Thu Nov 6 03:43:09 1997 +++ new/atm/test/Makefile Thu Mar 5 21:29:52 1998 @@ -1,6 +1,7 @@ ISP_OBJS=isp.o lex.yy.o y.tab.o USRPGMS=align aping aread awrite br bw isp ttcp_atm window MAN1= +TRASH=errnos.inc include ../Rules.make @@ -28,11 +29,13 @@ # # During "make depend", we need to have something that keeps the #include from # failing. The "touch" at the end makes sure that errnos.inc gets rebuilt in -# time. +# time. The sleep 1 makes sure that mkerrnos.pl is really more recent than +# errnos.inc # depend: fake_errnos.inc fake_errnos.inc: echo "! This must not compile" >errnos.inc + sleep 1 touch mkerrnos.pl diff -ur --new-file old/atm/test/README.isp new/atm/test/README.isp --- old/atm/test/README.isp Thu Jan 1 01:00:00 1970 +++ new/atm/test/README.isp Thu Mar 5 22:55:04 1998 @@ -0,0 +1,61 @@ +No man page yet. "isp" is a tool for sending and receiving ISP messages, +e.g. to test atmsigd. Although it can be used interactively, its poor +error handling makes it more suitable for script use. + +Commands: + + send msg_type [field=value|field=$var ...] + receive [msg_type [field=value|field=$var|$var=field ...]] + set $var=value + show + echo value + help + +where + + msg_type: bind, connect, accept, reject, listen, okay, error, indicate, + close, itf_notify, modify, identify + field: vcc, listen_vcc, reply, pvc, local, qos, svc, sap + +Variable syntax is like in Perl, i.e. a variable is always prefixed by +a dollar sign, even where it is not expanded. Fields and variables are +typed. Fields with compatible input have the same type (e.g. "svc" and +"local", and "vcc" and "listen_vcc"). The type of variables which are +set with "set" is determined the first time they're used in a "send" or +"receive" command. + +Fields which do not exist in a message cannot be accessed (see isp.c, +types[] for all valid combinations). Unspecified fields are set to +zero. isp does not enforce setting of mandatory fields (yet). + +"receive" accepts three types of arguments: + + field=value field must be equal to the value + field=$var field must be equal to the content of the variable + $var=field content of field is assigned to variable + +Values can contain pretty much any characters except for whitespace, +and they must not begin with dollar, equal, or hash signs. ispl.l +contains some hacks (e.g. {tail}) to make things work anyway. There is +no way to include whitespace in a value, so things like echo it works +don't work (but echo ?$\=# does). + +Examples: + + receive bind $VCC=vcc + send okay vcc=$VCC + + set $SAP = blli:l3=tr9577,ipi=snap,oui=0x00A03E,pid=0x0002 + send indicate listen_vcc=$VCC svc=+1007 qos=ubr:pcr=123kcps sap=$SAP + +isp normally pretty-prints all messages. This can be suppressed with +-q. + +A hint for regression test development: + + To test for pass, put echo PASSED after the command + To test for fail, put echo PASSED before and echo FAILED after + Check the last echo'ed string for PASSED (or nothing) + +The absence of conditional execution in isp's language is considered a +feature. diff -ur --new-file old/atm/test/aread.c new/atm/test/aread.c --- old/atm/test/aread.c Mon Nov 10 01:48:45 1997 +++ new/atm/test/aread.c Fri Feb 20 11:18:24 1998 @@ -1,6 +1,6 @@ /* aread.c - receive AAL5 PDU */ -/* Written 1995-1997 by Werner Almesberger, EPFL-LRC */ +/* Written 1995-1998 by Werner Almesberger, EPFL-LRC/ICA */ #include @@ -62,6 +62,8 @@ unsigned char *start; int size,i; + /* Make sure the buffer is aligned. This can be trivially extended to + play with alignments. */ start = (unsigned char *) (((unsigned long) buf+4095) & ~4095U); size = read(s,start,BSIZE); printf("%d",size); diff -ur --new-file old/atm/test/isp.c new/atm/test/isp.c --- old/atm/test/isp.c Tue Nov 18 01:50:11 1997 +++ new/atm/test/isp.c Thu Mar 5 22:31:27 1998 @@ -1,6 +1,6 @@ /* isp.c - Internal Signaling Protocol test generator */ -/* Written 1997 by Werner Almesberger, EPFL-ICA */ +/* Written 1997,1998 by Werner Almesberger, EPFL-ICA */ #include @@ -19,15 +19,17 @@ extern int yyparse(void); +int quiet = 0; +VAR *variables = NULL; -static int in,out; +static int input,output; void send_msg(const struct atmsvc_msg *msg) { int wrote; - wrote = write(out,msg,sizeof(*msg)); + wrote = write(output,msg,sizeof(*msg)); if (wrote == sizeof(*msg)) return; if (wrote < 0) perror("write"); else fprintf(stderr,"bad write: %d != %d\n",wrote,sizeof(*msg)); @@ -39,7 +41,7 @@ { int got; - got = read(in,msg,sizeof(*msg)); + got = read(input,msg,sizeof(*msg)); if (got == sizeof(*msg)) return; if (got < 0) perror("read"); else fprintf(stderr,"bad read: %d != %d\n",got,sizeof(*msg)); @@ -56,16 +58,6 @@ }; -int str2errno(const char *str) -{ - const struct errno_table *walk; - - for (walk = table; walk->name; walk++) - if (!strcmp(walk->name,str)) break; - return walk->value; -} - - static const char *errno2str(int code) { static char buf[30]; /* probably large enough :) */ @@ -83,92 +75,367 @@ } -#define F_VCC 0x00000001 -#define F_LISTEN 0x00000002 -#define F_REPLY 0x00000004 -#define F_PVC 0x00000008 -#define F_LOCAL 0x00000010 -#define F_QOS 0x00000020 -#define F_SVC 0x00000040 -#define F_SAP 0x00000080 +/* Synchronized with include/linux/atmsvc.h:enum atmsvc_msg_type */ + +static struct { + const char *name; + int fields; +} types[] = { + { "", 0 }, + { "bind", F_VCC | F_SVC | F_SAP }, + { "connect", F_VCC | F_PVC | F_LOCAL | F_QOS | F_SVC | F_SAP }, + { "accept", F_VCC | F_LISTEN_VCC }, + { "reject", F_VCC | F_LISTEN_VCC | F_REPLY }, + { "listen", F_VCC | F_QOS | F_SVC | F_SAP }, + { "okay", F_VCC | F_PVC | F_LOCAL | F_QOS | F_SVC | F_SAP }, + { "error", F_VCC | F_REPLY }, + { "indicate", F_LISTEN_VCC | F_PVC | F_LOCAL | F_QOS | F_SVC | F_SAP}, + { "close", F_VCC | F_REPLY }, + { "itf_notify", F_PVC }, + { "modify", F_VCC | F_REPLY | F_QOS }, + { "identify", F_VCC | F_LISTEN_VCC | F_PVC }}; +#define MSG_TYPES (sizeof(types)/sizeof(*types)) -void dump_msg(const struct atmsvc_msg *msg) + +void print_value(VALUE val) { - static struct { - enum atmsvc_msg_type type; - const char *name; - int fields; - } *type, types[] = { - { as_bind, "bind", F_VCC | F_SVC | F_SAP }, - { as_okay, "okay", F_VCC | F_PVC | F_LOCAL | F_QOS | - F_SVC | F_SAP }, - { as_connect, "connect", F_VCC | F_LOCAL | F_QOS | F_SVC | - F_SAP }, - { as_indicate, "indicate", F_LISTEN | F_QOS | F_SVC | F_SAP }, - { as_accept, "accept", F_VCC | F_LISTEN }, - { as_reject, "reject", F_LISTEN | F_REPLY }, - { as_error, "error", F_VCC | F_REPLY }, - { as_close, "close", F_VCC | F_REPLY }, - { as_itf_notify,"itf_notify", F_PVC }, - { as_modify, "modify", F_VCC | F_REPLY | F_QOS }, - { as_identify, "identify", F_VCC | F_LISTEN }, - { 0, NULL, 0 } - }; char buf[1000]; /* bigger than any MAX_ATM_*_LEN */ - for (type = types; type->name; type++) - if (type->type == msg->type) break; - if (!type->name) { - printf("Unknown type %d\n",(int) msg->type); + switch (val.type) { + case vt_text: + printf("\"%s\"",val.u.text); + return; + case vt_vcc: + printf("%d (0x%x)",val.u.num,val.u.num); + return; + case vt_error: + printf("%s",errno2str(val.u.num)); + return; + case vt_pvc: + if (atm2text(buf,sizeof(buf),(struct sockaddr *) &val.u.pvc, + A2T_PRETTY | A2T_NAME) < 0) strcpy(buf,""); + printf("%s",buf); + return; + case vt_svc: + if (atm2text(buf,sizeof(buf),(struct sockaddr *) &val.u.svc, + A2T_PRETTY | A2T_NAME) < 0) strcpy(buf,""); + printf("%s",buf); + return; + case vt_qos: + if (qos2text(buf,sizeof(buf),&val.u.qos,0) < 0) + strcpy(buf,""); + printf("%s",buf); + return; + case vt_sap: + if (sap2text(buf,sizeof(buf),&val.u.sap,S2T_NAME) < 0) + strcpy(buf,""); + printf("%s",buf); + return; + default: + fprintf(stderr,"\ninvalid value type %d\n",val.type); + exit(1); + } +} + + +#define FIELD(FLD,MSG) \ + if (fields & FLD) { \ + printf("%s",MSG); \ + print_value(pick(msg,FLD)); \ + putchar('\n'); \ + } + + +void dump_msg(const struct atmsvc_msg *msg) +{ + int fields; + + if (msg->type >= MSG_TYPES) { + printf("Unknown message type %d\n",msg->type); return; } - printf("Type=%s",type->name); - if (type->fields & F_VCC) - printf(", vcc=%ld (0x%lx)",msg->vcc,msg->vcc); - if (type->fields & F_LISTEN) - printf(", listen=%ld (0x%lx)",msg->listen_vcc,msg->listen_vcc); - if (type->fields & F_REPLY) - printf(", reply=%s",errno2str(msg->reply)); - if (type->fields & F_PVC) { - if (atm2text(buf,sizeof(buf),(struct sockaddr *) &msg->pvc, - A2T_PRETTY | A2T_NAME) < 0) strcpy(buf,""); - printf(",\n pvc=%s",buf); - } - if (type->fields & F_LOCAL) { - if (atm2text(buf,sizeof(buf),(struct sockaddr *) &msg->local, - A2T_PRETTY | A2T_NAME) < 0) strcpy(buf,""); - printf(",\n local=%s",buf); - } - if (type->fields & F_QOS) { - if (qos2text(buf,sizeof(buf),&msg->qos,0) < 0) strcpy(buf,""); - printf(",\n qos=%s",buf); - } - if (type->fields & F_SVC) { - if (atm2text(buf,sizeof(buf),(struct sockaddr *) &msg->svc, - A2T_PRETTY | A2T_NAME) < 0) strcpy(buf,""); - printf(",\n svc=%s",buf); - } - if (type->fields & F_SAP) { - if (sap2text(buf,sizeof(buf),&msg->sap,S2T_NAME) < 0) - strcpy(buf,""); - printf(",\n sap=%s",buf); + fields = types[msg->type].fields; + printf("Type: %s\n",types[msg->type].name); + FIELD(F_VCC, " vcc = "); + FIELD(F_LISTEN_VCC, " listen_vcc = "); + FIELD(F_REPLY, " reply = "); + FIELD(F_PVC, " pvc = "); + FIELD(F_LOCAL, " local = "); + FIELD(F_QOS, " qos = "); + FIELD(F_SVC, " svc = "); + FIELD(F_SAP, " sap = "); +} + + +#undef FIELD + + +VAR *create_var(const char *name) +{ + VAR *var,**walk; + + var = malloc(sizeof(VAR)); + if (!var) { + perror("malloc"); + exit(1); + } + var->name = name; /* strdup'ed */ + var->value.type = vt_none; + for (walk = &variables; *walk; walk = &(*walk)->next) + if (strcmp(name,(*walk)->name) > 0) break; + var->next = *walk; + *walk = var; + return var; +} + + +VAR *lookup(const char *name) +{ + VAR *var; + + for (var = variables; var; var = var->next) + if (!strcmp(var->name,name)) break; + return var; +} + + +static void destroy(VALUE value) +{ + if (value.type == vt_text) free((char *) value.u.text); +} + + +void assign(VAR *var,VALUE value) +{ + destroy(var->value); + var->value = value; +} + + +static int str2errno(const char *str) +{ + const struct errno_table *walk; + + for (walk = table; walk->name; walk++) + if (!strcmp(walk->name,str)) break; + return walk->value; +} + + +static VALUE convert(VALUE in,VALUE_TYPE type) +{ + VALUE out; + char *end; + + if (in.type == type) { + if (type == vt_text) { + in.u.text = strdup(in.u.text); + if (!in.u.text) { + perror("strdup"); + exit(1); + } + } + return in; + } + if (in.type != vt_text) yyerror("type conflict"); + out.type = type; + switch (type) { + case vt_vcc: + out.u.num = strtoul(in.u.text,&end,0); + if (*end) yyerror("invalid number"); + break; + case vt_error: + out.u.num = strtoul(in.u.text,&end,0); + if (*end) { + out.u.num = str2errno(*in.u.text == '-' ? in.u.text+1 : + in.u.text); + if (!out.u.num) yyerror("invalid error code"); + if (*in.u.text == '-') out.u.num = -out.u.num; + } + break; + case vt_svc: + if (text2atm(in.u.text,(struct sockaddr *) &out.u.svc, + sizeof(out.u.svc), T2A_SVC | T2A_NAME) < 0) + yyerror("invalid SVC address"); + break; + case vt_pvc: + if (text2atm(in.u.text,(struct sockaddr *) &out.u.pvc, + sizeof(out.u.pvc),T2A_PVC | T2A_NNI | T2A_NAME) < 0) + yyerror("invalid PVC address"); + break; + case vt_qos: + if (text2qos(in.u.text,&out.u.qos,0) < 0) yyerror("invalid QOS"); + break; + case vt_sap: + if (text2sap(in.u.text,&out.u.sap,T2S_NAME) < 0) + yyerror("invalid SAP address"); + break; + default: + fprintf(stderr,"unexpected conversion type %d\n",type); + exit(1); + } + return out; +} + + +void check(VALUE a,VALUE b) +{ + if (a.type == vt_text) a = convert(a,b.type); + if (b.type == vt_text) b = convert(b,a.type); + if (a.type != b.type) yyerror("type conflict"); + switch (a.type) { + case vt_vcc: + case vt_error: + if (a.u.num == b.u.num) return; + break; + case vt_svc: + if (atm_equal(&a.u.svc,&b.u.svc,0,0)) return; + break; + case vt_pvc: + if (a.u.pvc.sap_addr.itf == b.u.pvc.sap_addr.itf && + a.u.pvc.sap_addr.vpi == b.u.pvc.sap_addr.vpi && + a.u.pvc.sap_addr.vci == b.u.pvc.sap_addr.vci) return; + break; + case vt_qos: + if (qos_equal(&a.u.qos,&b.u.qos)) return; + break; + case vt_sap: + if (sap_equal(&a.u.sap,&b.u.sap,0)) return; + break; + default: + fprintf(stderr,"unexpected conversion type %d\n",a.type); + exit(1); + } + printf("Expected "); + print_value(b); + printf(",\nbut message contains "); + print_value(a); + printf("\n"); + exit(1); +} + + +#define COPY_MSG_VAL(V) \ + switch (field) { \ + case F_VCC: _COPY(V.u.num,msg->vcc); break; \ + case F_LISTEN_VCC: _COPY(V.u.num,msg->listen_vcc); break; \ + case F_REPLY: _COPY(V.u.num,msg->reply); break; \ + case F_PVC: _COPY(V.u.pvc,msg->pvc); break; \ + case F_LOCAL: _COPY(V.u.svc,msg->local); break; \ + case F_QOS: _COPY(V.u.qos,msg->qos); break; \ + case F_SVC: _COPY(V.u.svc,msg->svc); break; \ + case F_SAP: _COPY(V.u.sap,msg->sap); break; \ + default: fprintf(stderr,"unexpected field type 0x%x\n",field); \ + exit(1); \ + } + + + +VALUE pick(const struct atmsvc_msg *msg,int field) +{ + VALUE out; + + if (msg->type >= MSG_TYPES) { + fprintf(stderr,"invalid message type %d",msg->type); + exit(1); + } + if (!(types[msg->type].fields & field)) yyerror("no such field in message"); + out.type = type_of(field); +#define _COPY(V,M) V = M +COPY_MSG_VAL(out) +#undef _COPY + return out; +} + + +void store(struct atmsvc_msg *msg,int field,VALUE val) +{ + if (msg->type >= MSG_TYPES) { + fprintf(stderr,"invalid message type %d",msg->type); + exit(1); + } + if (!(types[msg->type].fields & field)) yyerror("no such field in message"); + if (val.type != type_of(field)) yyerror("type conflict"); +#define _COPY(V,M) M = V +COPY_MSG_VAL(val) +#undef _COPY +} + + +#undef COPY_MSG_VAL + + +VALUE eval(VALUE_TYPE type,const char *str) +{ + VALUE a,b; + + a.type = vt_text; + a.u.text = strdup(str); + if (!a.u.text) { + perror("strdup"); + exit(1); + } + b = convert(a,type); + destroy(a); + return b; +} + + +void cast(VAR *var,VALUE_TYPE type) +{ + VALUE old; + + if (var->value.type == type) return; + old = var->value; + var->value = convert(var->value,type); + destroy(old); +} + + +VALUE_TYPE type_of(int field) +{ + switch (field) { + case F_VCC: + case F_LISTEN_VCC: + return vt_vcc; + case F_REPLY: + return vt_error; + case F_PVC: + return vt_pvc; + case F_LOCAL: + case F_SVC: + return vt_svc; + case F_QOS: + return vt_qos; + case F_SAP: + return vt_sap; + default: + fprintf(stderr,"unexpected field type 0x%x\n",field); + exit(1); } - putchar('\n'); } int main(int argc,char **argv) { + const char *name; + + name = *argv; + if (argc > 3 && !strcmp(argv[1],"-q")) { + quiet = 1; + argc--; + argv++; + } if (argc != 3) { - fprintf(stderr,"usage: %s input output\n",*argv); + fprintf(stderr,"usage: %s [-q] input output\n",name); return 1; } - if ((in = open(argv[1],O_RDWR)) < 0) { /* actually read-only */ + if ((input = open(argv[1],O_RDWR)) < 0) { /* actually read-only */ perror(argv[1]); return 1; } - if ((out = open(argv[2],O_RDWR)) < 0) { /* actually write-only */ + if ((output = open(argv[2],O_RDWR)) < 0) { /* actually write-only */ perror(argv[2]); return 1; } diff -ur --new-file old/atm/test/isp.h new/atm/test/isp.h --- old/atm/test/isp.h Sat Nov 1 19:29:45 1997 +++ new/atm/test/isp.h Thu Mar 5 20:41:58 1998 @@ -1,17 +1,68 @@ /* isp.h - Internal Signaling Protocol test generator */ -/* Written 1997 by Werner Almesberger, EPFL-ICA */ +/* Written 1997,1998 by Werner Almesberger, EPFL-ICA */ #ifndef ISP_H #define ISP_H +#include #include +/* Field type values */ + +#define F_VCC 0x00000001 +#define F_LISTEN_VCC 0x00000002 +#define F_REPLY 0x00000004 +#define F_PVC 0x00000008 +#define F_LOCAL 0x00000010 +#define F_QOS 0x00000020 +#define F_SVC 0x00000040 +#define F_SAP 0x00000080 + + +typedef enum { vt_none,vt_text,vt_vcc,vt_error,vt_svc,vt_pvc,vt_qos,vt_sap } + VALUE_TYPE; + +typedef struct { + VALUE_TYPE type; + union { + const char *text; + int num; + struct sockaddr_atmsvc svc; + struct sockaddr_atmpvc pvc; + struct atm_qos qos; + struct atm_sap sap; + } u; +} VALUE; + +typedef struct _var { + const char *name; + VALUE value; + struct _var *next; +} VAR; + + +extern int quiet; +extern VAR *variables; + + +void yyerror(const char *s); + +void print_value(VALUE val); +VAR *create_var(const char *name); +VAR *lookup(const char *name); +void assign(VAR *var,VALUE value); +void check(VALUE a,VALUE b); +VALUE pick(const struct atmsvc_msg *msg,int field); +void store(struct atmsvc_msg *msg,int field,VALUE val); +VALUE eval(VALUE_TYPE type,const char *str); +void cast(VAR *var,VALUE_TYPE type); +VALUE_TYPE type_of(int field); + void send_msg(const struct atmsvc_msg *msg); void recv_msg(struct atmsvc_msg *msg); void dump_msg(const struct atmsvc_msg *msg); -int str2errno(const char *str); #endif diff -ur --new-file old/atm/test/ispl.l new/atm/test/ispl.l --- old/atm/test/ispl.l Tue Nov 18 01:47:55 1997 +++ new/atm/test/ispl.l Thu Mar 5 22:26:17 1998 @@ -1,7 +1,7 @@ %{ /* isp.l - Internal Signaling Protocol test generator language */ -/* Written 1997 by Werner Almesberger, EPFL-ICA */ +/* Written 1997,1998 by Werner Almesberger, EPFL-ICA */ #include @@ -9,27 +9,35 @@ #include #include + +#include "isp.h" #include "y.tab.h" static int lineno = 1; -void yyerror(const char *s); - %} +tail ([^a-zA-Z0-9]|$|[ \t\n]*=.*) + %% send return TOK_SEND; wait return TOK_WAIT; -vcc return TOK_VCC; +receive return TOK_RECEIVE; +help return TOK_HELP; +set return TOK_SET; +show return TOK_SHOW; +echo return TOK_ECHO; +vcc/{tail} return TOK_VCC; +listen_vcc/{tail} return TOK_LISTEN_VCC; +reply/{tail} return TOK_REPLY; +pvc/{tail} return TOK_PVC; +local/{tail} return TOK_LOCAL; +qos/{tail} return TOK_QOS; +svc/{tail} return TOK_SVC; +sap/{tail} return TOK_SAP; listen return TOK_LISTEN; -reply return TOK_REPLY; -pvc return TOK_PVC; -local return TOK_LOCAL; -qos return TOK_QOS; -svc return TOK_SVC; -sap return TOK_SAP; bind return TOK_BIND; connect return TOK_CONNECT; accept return TOK_ACCEPT; @@ -41,26 +49,29 @@ itf_notify return TOK_ITF_NOTIFY; modify return TOK_MODIFY; identify return TOK_IDENTIFY; -=[ \t]*[^ \t\n]* { - const char *start; - - for (start = yytext+1; strchr(" \t\n",*start); - start++); - yylval.str = strdup(start); +\\[\t ]*\n lineno++; +#[^\n]*\n lineno++; +[^ \t\n\$=][^ \t\n]* { + yylval.str = strdup(yytext); if (!yylval.str) { perror("strdup"); exit(1); } return TOK_VALUE; } -\n?[\t ]* { - if (*yytext == '\n') { - lineno++; - return TOK_EOL; +\$[0-9a-zA-Z_]+ { + yylval.str = strdup(yytext+1); + if (!yylval.str) { + perror("strdup"); + exit(1); } + return TOK_VARIABLE; } -\\[\t ]*\n lineno++; -#[^\n]*\n lineno++; +\n { + lineno++; + return TOK_EOL; + } +[\t ]* ; . return *yytext; %% diff -ur --new-file old/atm/test/ispl.y new/atm/test/ispl.y --- old/atm/test/ispl.y Tue Nov 18 01:48:31 1997 +++ new/atm/test/ispl.y Thu Mar 5 22:03:15 1998 @@ -1,10 +1,12 @@ %{ /* isp.y - Internal Signaling Protocol test generator language */ -/* Written 1997 by Werner Almesberger, EPFL-ICA */ +/* Written 1997,1998 by Werner Almesberger, EPFL-ICA */ #include +#include +#include #include #include #include @@ -14,22 +16,28 @@ static struct atmsvc_msg msg; + %} %union { char *str; + int num; enum atmsvc_msg_type type; + VAR *var; }; -%token TOK_SEND TOK_WAIT TOK_VCC TOK_LISTEN TOK_REPLY TOK_PVC +%token TOK_SEND TOK_WAIT TOK_RECEIVE TOK_HELP TOK_SET TOK_SHOW TOK_ECHO +%token TOK_VCC TOK_LISTEN TOK_LISTEN_VCC TOK_REPLY TOK_PVC %token TOK_LOCAL TOK_QOS TOK_SVC TOK_BIND TOK_CONNECT TOK_ACCEPT %token TOK_REJECT TOK_LISTEN TOK_OKAY TOK_ERROR TOK_INDICATE -%token TOK_CLOSE TOK_ITF_NOTIFY TOK_MODIFY TOK_SAP TOK_EOL -%token TOK_IDENTIFY -%token TOK_VALUE +%token TOK_CLOSE TOK_ITF_NOTIFY TOK_MODIFY TOK_SAP +%token TOK_IDENTIFY TOK_EOL +%token TOK_VALUE TOK_VARIABLE %type type +%type field_type number +%type new_var old_var %% @@ -43,14 +51,53 @@ memset(&msg,0,sizeof(msg)); msg.type = $2; } - values TOK_EOL + values { send_msg(&msg); } - | TOK_WAIT TOK_EOL + | TOK_RECEIVE { recv_msg(&msg); - dump_msg(&msg); + if (!quiet) dump_msg(&msg); + } + opt_recv + | TOK_WAIT number + { + sleep($2); + } + | TOK_SET new_var '=' TOK_VALUE + { + assign($2,eval(vt_text,$4)); + free($4); + } + | TOK_SHOW + { + VAR *var; + + for (var = variables; var; var = var->next) { + printf("%s = ",var->name); + print_value(var->value); + putchar('\n'); + } + } + | TOK_ECHO TOK_VALUE + { + printf("%s\n",$2); + free($2); + } + | help + { + fprintf(stderr, +"Commands:\n" +" send msg_type [field=value|field=$var ...]\n" +" receive [msg_type [field=value|field=$var|$var=field ...]]\n" +" set $var=value\n" +" show\n" +" echo value\n" +" help\n\n" +"msg_type: bind, connect, accept, reject, listen, okay, error, indicate,\n" +" close, itf_notify, modify, identify\n" +"field: vcc, listen_vcc, reply, pvc, local, qos, svc, sap\n"); } | TOK_EOL ; @@ -111,67 +158,112 @@ ; value: - TOK_VCC TOK_VALUE + field_type '=' old_var + { + cast($3,type_of($1)); + store(&msg,$1,$3->value); + } + | field_type '=' TOK_VALUE + { + store(&msg,$1,eval(type_of($1),$3)); + free($3); + } + ; + +number: + TOK_VALUE { char *end; - msg.vcc = strtoul($2,&end,0); - if (*end) yyerror("invalid VCC id"); - free($2); + $$ = strtol($1,&end,10); + if (*end) yyerror("invalid number"); + free($1); } - | TOK_LISTEN TOK_VALUE + ; + +opt_recv: + | type { - char *end; + if (msg.type != $1) yyerror("wrong message type"); + } + fields + ; - msg.listen_vcc = strtoul($2,&end,0); - if (*end) yyerror("invalid VCC id"); - free($2); +fields: + | field fields + ; + +field: + new_var '=' field_type + { + assign($1,pick(&msg,$3)); } - | TOK_REPLY TOK_VALUE + | field_type '=' old_var { - char *end; + cast($3,type_of($1)); + check(pick(&msg,$1),$3->value); + } + | field_type '=' TOK_VALUE + { + check(pick(&msg,$1),eval(type_of($1),$3)); + free($3); + } + ; - msg.reply = strtol($2,&end,0); - if (*end) { - int code; - - code = str2errno(*$2 == '-' ? $2+1 : $2); - if (!code) yyerror("invalid error code"); - msg.reply = *$2 == '-' ? -code : code; - } - free($2); +field_type: + TOK_VCC + { + $$ = F_VCC; } - | TOK_PVC TOK_VALUE + | TOK_LISTEN_VCC { - if (text2atm($2,(struct sockaddr *) &msg.pvc,sizeof(msg.pvc), - T2A_PVC | T2A_NNI | T2A_NAME) < 0) - yyerror("invalid PVC address"); - free($2); + $$ = F_LISTEN_VCC; } - | TOK_LOCAL TOK_VALUE + | TOK_REPLY { - if (text2atm($2,(struct sockaddr *) &msg.local,sizeof(msg.local), - T2A_SVC | T2A_NAME) < 0) - yyerror("invalid SVC address"); - free($2); + $$ = F_REPLY; } - | TOK_QOS TOK_VALUE + | TOK_PVC { - if (text2qos($2,&msg.qos,0) < 0) - yyerror("invalid QOS"); - free($2); + $$ = F_PVC; } - | TOK_SVC TOK_VALUE + | TOK_LOCAL { - if (text2atm($2,(struct sockaddr *) &msg.svc,sizeof(msg.svc), - T2A_SVC | T2A_NAME) < 0) - yyerror("invalid SVC address"); - free($2); + $$ = F_LOCAL; } - | TOK_SAP TOK_VALUE + | TOK_QOS { - if (text2sap($2,&msg.sap,T2S_NAME) < 0) - yyerror("invalid SAP address"); - free($2); + $$ = F_QOS; + } + | TOK_SVC + { + $$ = F_SVC; + } + | TOK_SAP + { + $$ = F_SAP; + } + ; + +help: + TOK_HELP + | '?' + ; + +new_var: + TOK_VARIABLE + { + $$ = lookup($1); + if ($$) free($1); + else $$ = create_var($1); + } + ; + +old_var: + TOK_VARIABLE + { + $$ = lookup($1); + if (!$$) yyerror("no such variable"); + free($1); } ; .