From ce56f3183d9b98552f7e5abb7dc8b4eb8b3fe5ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?cristian=20paul=20pe=C3=B1aranda=20rojas?= Date: Sat, 29 Nov 2008 00:31:58 -0500 Subject: [PATCH] Imported Debian version 1.2.2~svn3653 --- COPYING | 674 ++++++ HACKING | 196 ++ INSTALL | 50 + Makefile | 64 + README | 95 + debian/README.Debian | 34 + debian/changelog | 6 + debian/compat | 1 + debian/control | 14 + debian/copyright | 110 + debian/dirs | 2 + debian/docs | 1 + debian/patches/01-edge.8.diff | 8 + debian/patches/series | 1 + debian/rules | 79 + edge.8 | 77 + edge.c | 1407 +++++++++++ lzoconf.h | 417 ++++ lzodefs.h | 1807 +++++++++++++++ minilzo.c | 4112 +++++++++++++++++++++++++++++++++ minilzo.h | 106 + n2n.c | 892 +++++++ n2n.h | 290 +++ n2n.spec | 47 + openwrt/kamikaze/Makefile | 55 + scripts/mk_SRPM.sh | 30 + scripts/mk_deb.sh | 46 + scripts/mk_tar.sh | 105 + supernode.1 | 32 + supernode.c | 525 +++++ tuntap_freebsd.c | 124 + tuntap_linux.c | 122 + tuntap_osx.c | 124 + twofish.c | 1031 +++++++++ twofish.h | 281 +++ 35 files changed, 12965 insertions(+) create mode 100644 COPYING create mode 100644 HACKING create mode 100644 INSTALL create mode 100644 Makefile create mode 100644 README create mode 100644 debian/README.Debian create mode 100644 debian/changelog create mode 100644 debian/compat create mode 100644 debian/control create mode 100644 debian/copyright create mode 100644 debian/dirs create mode 100644 debian/docs create mode 100644 debian/patches/01-edge.8.diff create mode 100644 debian/patches/series create mode 100755 debian/rules create mode 100644 edge.8 create mode 100644 edge.c create mode 100644 lzoconf.h create mode 100644 lzodefs.h create mode 100644 minilzo.c create mode 100644 minilzo.h create mode 100644 n2n.c create mode 100644 n2n.h create mode 100644 n2n.spec create mode 100644 openwrt/kamikaze/Makefile create mode 100755 scripts/mk_SRPM.sh create mode 100755 scripts/mk_deb.sh create mode 100755 scripts/mk_tar.sh create mode 100644 supernode.1 create mode 100644 supernode.c create mode 100644 tuntap_freebsd.c create mode 100644 tuntap_linux.c create mode 100644 tuntap_osx.c create mode 100644 twofish.c create mode 100644 twofish.h diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..b33b35d --- /dev/null +++ b/COPYING @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them 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 prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If 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 convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state 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 program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + n2n Copyright (C) 2007-08 Luca Deri + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/HACKING b/HACKING new file mode 100644 index 0000000..24b4d46 --- /dev/null +++ b/HACKING @@ -0,0 +1,196 @@ +file: HACKING + +Last updated: 2008-04-10 + +-------- +(C) 2008 - Richard Andrews + +This program and document is free software; you can redistribute +it and/or modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 3 of the +License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not see see + +-------- + + +This file describes the internals of n2n. Read this before starting to modify +the code. Because coding examples may be present in this document it is licensed +under the GPL rather than FDL. + + +SYMMETRIC NAT +------------- + +Symmetric NAT is a form of firewall NAT in which an UDP packets are only passed +back to an inside host socket when the return packets originate from the outside +socket to which the initiating UDP packets were sent. This means that when an +inside host sends UDP to some outside socket; other hosts cannot piggyback on +this opening in the firewall to send data to the inside host. + +When two inside hosts are both behind symmetric NAT, peer-to-peer packet +exchange is not possible via n2n. These hosts will require the supernode to +relay packets. + + +ARP CACHE +--------- + +n2n makes use of the host operating system's own ARP cache. Each edge node +allocates a random MAC address to itself. This MAC is constant for the life of +the edge process. ARP packets are passed around as broadcast ethernet packets +over n2n and these packets cause the native ARP cache to be updated. + +Edge nodes send gratuitous ARP packets on startup. See GRATUITOUS ARP below. + + +REGISTRATION AND PEER-TO-PEER COMMUNICATION SETUP +------------------------------------------------- + +A and B are edge nodes with public sockets Apub and Bpub; and private network +addresses A and B respectively. S is the supernode. + +A sends {REGISTER,Amac} to S. S registers {Amac->Apub}. +B sends {REGISTER,Bmac} to S. S registers {Bmac->Bpub}. + +Now ping from A to B. + +A sends broadcast "arp who-has B" to S. S relays the packet to all known edge +nodes. B replies "B at Bmac" to supernode which forwards this to A. So now ping +A->B is known to be ping Amac(A)->Bmac(B). Note: gratuitous arp also requires +discussion. + +In response to receiving the arp reply, Apub sends {REGISTER,Amac} to Bpub. If +Bpub receives the request it sends back {REGISTER_ACK,Amac} and also sends its +own {REGISTER,Bmac} request. + +In response to receiving the "arp who-has", Bpub sends {REGISTER,Bmac} to Apub. + +Now the OS has received the arp reply and sends ICMP to Bmac(B) via the tunnel +on A. A looks up Bmac in the peers list and encapsulates the packet to Bpub or +the supernode if the MAC is not found. + +We assume that between two edge nodes, if Bpub receives a packet from Apub then +Apub can receive a packet from Bpub. This is the symmetric NAT case. Note: In +the symmetric NAT case, the public socket for a MAC address will be different +for direct contact when compared to information from the supernode. + +When two edge nodes are both behind symmetric NAT they cannot establish direct +communication. + +If A receives {REGISTER,Bmac} from B, A adds {Bmac->Bpub} to its peers list +knowing that Bmac is now reachable via that public socket. Similarly if B +receives {REGISTER,Amac} from A. + +The supernode never forwards REGISTER messages because the public socket seen by +the supervisor for some edge (eg. A) may be different to the socket seen by +another edge due to the actions of symmetric NAT (alocating a new public socket +for the new outbound UDP "connection"). + + +EDGE REGISTRATION DESIGN AMMENDMENTS (starting from 2008-04-10) +------------------------------------ + + * Send REGISTER on rx of PACKET or REGISTER only when dest_mac == device MAC +(do not send REGISTER on Rx of broadcast packets). + * After sending REGISTER add the new peer to pending_peers list; but + * Don't send REGISTER to a peer in pending_peers list + * Remove old entries from pending_peers at regular intervals + * On rx of REGISTER_ACK, move peer from pending_peers to known_peers for direct +comms and set last_seen=now + * On rx of any packet set last_seen=now in the known_peers entry (if it +exists); but do not add a new entry. + * If the public socket address for a known_peers entry changes, deleted it and +restart registration to the new peer. + * Peer sockets provided by the supernode are ignored unless no other entry +exists. Direct peer-to-peer sockets are always given more priority as the +supernode socket will not be usable for direct contact if the peer is behind +symmetric NAT. + + +The pending_peers list concept is to prevent massive registration traffic when +supernode relay is in force - this would occur if REGISTER was sent for every +incident packet sent via supernode. Periodic REGISTER attempts will still occur; +not for every received packet. In the case where the peer cannot be contacted +(eg. both peers behind symmetric NAT), then there will still be periodic +attempts. Suggest a pending timeout of about 60 sec. + +A peer is only considered operational for peer-to-peer sending when a +REGISTER_ACK is returned. Once operational the peer is kept operational while +any direct packet communications are occurring. REGISTER is not required to +keep the path open through any firewalls; just some activity in one direction. + +After an idle period; the peer should be deleted from the known_peers list. We +should not try to re-register when this time expires. If there is no data to +send then forget the peer. This helps scalability. + +If a peer wants to be remembered it can send gratuitous ARP traffic which will +keep its entry in the known_peers list of any peers which already have the +entry. + + + + +peer = find_by_src_mac( hdr, known_peers ); /* return NULL or entry */ + +if ( peer ) +{ + peer_last_seen = time(NULL); +} +else +{ + if ( ! is_broadcast( hdr ) ) /* ignore broadcasts */ + { + if ( IS_REGISTER_ACK( hdr ) ) + { + /* move from pending to known_peers */ + set_peer_operational( hdr ); + } + else + { + /* add to pending and send REGISTER - ignore if in pending. */ + try_send_register( hdr ) + } + } +} + + +(Notes): + + * In testing it was noted that if a symmetric NAT firewall shuts down the UDP +association but the known_peers registration is still active, then the peer +becomes unreachable until the known_peers registration is deleted. Suggest two +ways to mitigate this problem: + (a) make the known_peers purge timeout a config paramter; + (b) send packets direct and via supernode if the registration is older than + eg. 60 sec. + + +GRATUITOUS ARP +-------------- + +In addition to the ARP who-has mechanism noted above, two edge nodes can become +aware of one another by gratuitous ARP. A gratuitous ARP packet is a broadcast +packet sent by a node for no other purpose than to announce its presence and +identify its MAC and IP address. Gratuitous ARP packets are to keep ARP caches +up to date so contacting the host will be faster after an long idle time. + + +MAN PAGES +--------- + +Look at a non-installed man page like this (linux): + +nroff -man edge.8 | less + + +------- + +April 2008 - Richard Andrews diff --git a/INSTALL b/INSTALL new file mode 100644 index 0000000..d6e7a7b --- /dev/null +++ b/INSTALL @@ -0,0 +1,50 @@ +INSTALL + +To build the programs: + +$ make + +To install the programs and man pages: + +$ make install + +or + +$ make PREFIX=/usr/local install + + +RPM Package +----------- + +These steps should work with RPM based Linux distributions since rpmbuild was +split from the rpm utility (c RedHat 9). + + +To build an RPM the easy way follow these steps. + +1. Build SRPM + +$ cd n2n +$ scripts/mk_SRPM.sh + +Look for where the src.rpm file was put ( "Wrote:" ). + +2. Build binary RPM from SRPM + +$ rpm -i path/to/n2n-.src.rpm +$ rpmbuild -bb n2n.spec + + +All this can be done as non-root user if you have a ~/.rpmmacros file with this +line in it: + +%_topdir /home/username/rpmtopdir + + +To build an RPM the hard way follow these steps. + +$ cp -a n2ndir n2n-1.2 +$ tar czf n2n-1.2.tar.gz n2n-1.2 +$ mv n2n-1.2.tar.gz /usr/src/redhat/SOURCES +$ cp n2ndir/n2n.spec /usr/src/redhat/SPECS +$ rpmbuild -bb n2n.spec diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..d53272a --- /dev/null +++ b/Makefile @@ -0,0 +1,64 @@ + +N2N_VERSION="1.2.2" + + +######## + +CC=gcc +CFLAGS+=-g -Wall -Wshadow -Wpointer-arith -Wmissing-declarations -Wnested-externs #-static + +INSTALL=install +MKDIR=mkdir -p + +INSTALL_PROG=$(INSTALL) -m755 +INSTALL_DOC=$(INSTALL) -m644 + + +# DESTDIR set in debian make system +PREFIX?=$(DESTDIR)/usr +BINDIR=$(PREFIX)/bin +SBINDIR=$(PREFIX)/sbin +MANDIR?=$(PREFIX)/share/man +MAN1DIR=$(MANDIR)/man1 +MAN8DIR=$(MANDIR)/man8 + +N2N_LIB=n2n.a +N2N_OBJS=n2n.o minilzo.o twofish.o tuntap_freebsd.o tuntap_linux.o tuntap_osx.o version.o +LIBS=-lpthread + +APPS=edge supernode +DOCS=edge.8.gz supernode.1.gz + +all: $(APPS) #$(DOCS) + +edge: edge.c $(N2N_LIB) n2n.h Makefile + $(CC) $(CFLAGS) edge.c $(N2N_LIB) $(LIBS) -o edge + +supernode: supernode.c $(N2N_LIB) n2n.h Makefile + $(CC) $(CFLAGS) supernode.c $(N2N_LIB) $(LIBS) -o supernode + +.c.o: n2n.h Makefile + $(CC) $(CFLAGS) -c $< + +%.gz : % + gzip -c $< > $@ + +$(N2N_LIB): $(N2N_OBJS) + ar rcs $(N2N_LIB) $(N2N_OBJS) +# $(RANLIB) $@ + +version.c: + echo $(N2N_VERSION) | sed -e 's/.*/char * version = "&";/' > version.c + uname -p | sed -e 's/.*/char * osName = "&";/' >> version.c + date +"%D %r" | sed -e 's/.*/char * buildDate = "&";/' >> version.c + +clean: + rm -rf $(N2N_OBJS) $(N2N_LIB) $(APPS) $(DOCS) *.dSYM *~ version.c + +install: edge supernode edge.8.gz supernode.1.gz + echo "MANDIR=$(MANDIR)" + $(MKDIR) $(BINDIR) $(SBINDIR) $(MAN1DIR) $(MAN8DIR) + $(INSTALL_PROG) supernode $(BINDIR)/ + $(INSTALL_PROG) edge $(SBINDIR)/ + $(INSTALL_DOC) edge.8.gz $(MAN8DIR)/ + $(INSTALL_DOC) supernode.1.gz $(MAN1DIR)/ diff --git a/README b/README new file mode 100644 index 0000000..e021f41 --- /dev/null +++ b/README @@ -0,0 +1,95 @@ + + +Edge node +--------- + +You need to start an egde node on each host you want to connect with the *same* +community. + +0. become root + +1. create tun device +# tunctl -t tun0 + +3. enable the edge process +# ./edge -d n2n0 -c mynetwork -k encryptme -u 99 -g 99 -m 3C:A0:12:34:56:78 -a 1.2.3.4 -l a.b.c.d:xyw + or +# N2N_KEY=encryptme ./edge -d n2n0 -c mynetwork -u 99 -g 99 -m 3C:A0:12:34:56:78 -a 1.2.3.4 -l a.b.c.d:xyw + +Once you have this worked out, you can add the "-f" option to make edge detach +and run as a daemon. + +Note that -u, -g and -f options are not available for Windows. + +Supernode +-------- + +You need to start the supernode once + +1. ./supernode -l 1234 -v + + +Dropping Root Privileges and SUID-Root Executables (UNIX) +-------------------------------------------------- + +The edge node uses superuser privileges to create a TAP network interface +device. Once this is created root privileges are not required and can constitute +a security hazard if there is some way for an attacker to take control of an +edge process while it is running. Edge will drop to a non-privileged user if you +specify the -u and -g options. These are numeric IDs. Consult +/etc/passwd. + +You may choose to install edge SUID-root to do this: + +1. Become root +2. chown root:root edge +3. chmod +s edge +done + +Any user can now run edge. You may not want this, but it may be convenient and +safe if your host has only one login user. + + +Running As a Daemon (UNIX) +------------------- + +When given "-f" as a command line option, edge will call daemon(3) after +successful setup. This causes the process to fork a child which closes stdin, +stdout and stderr then sets itself as process group leader. When this is done, +the edge command returns immediately and you will only see the edge process in +the process listings, eg. from ps or top. + +If the edge command returns 0 then the daemon started successfully. If it +returns non-zero then edge failed to start up for some reason. When edge starts +running as a daemon, all logging goes to syslog daemon.info facility. + + +IPv6 Support (added r3650) +------------ + +n2n supports the carriage of IPv6 packets within the n2n tunnel. N2n does not +yet use IPv6 for transport between edges and supernodes. + +To make IPv6 carriage work you need to manually add IPv6 addresses to the TAP +interfaces at each end. There is currently no way to specify an IPv6 address on +the edge command line. + +eg. under linux: + +on hostA: +[hostA] # /sbin/ip -6 addr add fc00:abcd:1234::7/48 dev n2n0 + +on hostB: +[hostB] # /sbin/ip -6 addr add fc00:abcd:1234::6/48 dev n2n0 + +You may find it useful to make use of tunctl from the uml-utilities +package. Tunctl allow you to bring up a TAP interface and configure addressing +prior to starting edge. It also allows edge to be restarted without the +interface closing (which would normally affect routing tables). + +Once the IPv6 addresses are configured and edge started, IPv6 neighbor discovery +packets flow (get broadcast) and IPv6 entities self arrange. Test your IPv6 +setup with ping6 - the IPv6 ping command. + + +(C) 2007,2008 - Luca Deri , Richard Andrews diff --git a/debian/README.Debian b/debian/README.Debian new file mode 100644 index 0000000..3c58a22 --- /dev/null +++ b/debian/README.Debian @@ -0,0 +1,34 @@ +n2n for Debian +-------------- + +This package depends on the kernel having the TUN/TAP driver configured in using +CONFIG_TUN=yes. + + +Quickstart +---------- + + * Decide where to place your supernode. Suppose you put it on host a.b.c.d +at port xyw. + * Decide what encryption password you want to use to secure your data. +Suppose you use the password encryptme + * Decide the network name you want to use. Suppose you call it mynetwork. +Note that you can use your supernode/edge nodes to handle multiple networks, +not just one. + * Decide what IP address you plan to use on your edge nodes. Suppose you +use IP address 10.1.2.0/24 + * Start your applications: + + o #supernode > supernode -l xyw + o #edge node1> edge -a 10.1.2.1 -c mynetwork -k encryptme -l a.b.c.d:xyw + o #edge node2> edge -a 10.1.2.2 -c mynetwork -k encryptme -l a.b.c.d:xyw + + Now test your n2n network: + + o #edge node1> ping 10.1.2.2 + o #edge node2> ping 10.1.2.1 + +For more info check http://www.ntop.org/n2n + + + -- cristian paul peñaranda rojas Sat, 29 Nov 2008 00:31:58 -0500 diff --git a/debian/changelog b/debian/changelog new file mode 100644 index 0000000..a5da4cf --- /dev/null +++ b/debian/changelog @@ -0,0 +1,6 @@ +n2n (1.2.2~svn3653) unstable; urgency=low + + * Initial release (closes: Bug#507750) + + -- cristian paul peñaranda rojas Sat, 29 Nov 2008 00:31:58 -0500 + diff --git a/debian/compat b/debian/compat new file mode 100644 index 0000000..7ed6ff8 --- /dev/null +++ b/debian/compat @@ -0,0 +1 @@ +5 diff --git a/debian/control b/debian/control new file mode 100644 index 0000000..e025500 --- /dev/null +++ b/debian/control @@ -0,0 +1,14 @@ +Source: n2n +Section: net +Priority: extra +Maintainer: cristian paul peñaranda rojas +Build-Depends: debhelper (>= 5), libc6-dev (>= 2.0), quilt +Standards-Version: 3.8.0 + +Package: n2n +Architecture: any +Depends: ${shlibs:Depends} +Description: Peer-to-Peer VPN network daemon + n2n is an open source VPN application which utilizes + a Peer-to-peer architecture for network membership + and routing. diff --git a/debian/copyright b/debian/copyright new file mode 100644 index 0000000..6e4cae6 --- /dev/null +++ b/debian/copyright @@ -0,0 +1,110 @@ +This package was debianized by cristian paul peñaranda rojas on +and is licensed under the GNU General Public License (GPL) version 3. +A copy of the GNU GPL version 2 is in `/usr/share/common-licenses/GPL-3'. + +Sat, 29 Nov 2008 00:31:58 -0500. + +The current Debian maintainer is cristian paul peñaranda rojas + +It was downloaded from https://svn.ntop.org/svn/ntop/trunk/n2n + +Upstream Author: Luca Deri deri@ntop.org + +Copyright: + + Copyright (C) 2008 Luca Deri + Copyright (C) 2008 Richard Andrews + + +License: + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License with + the Debian GNU/Linux distribution in file /usr/share/common-licenses/GPL; + if not, write to the Free Software Foundation, Inc., 51 Franklin St, + Fifth Floor, Boston, MA 02110-1301, USA. + + + On Debian systems, the complete text of the GNU General Public + License, version 3, can be found in /usr/share/common-licenses/GPL-3. + +The Files: + + twofish.c + twofish.h + + Copyright (C) 1997-2000 The Cryptix Foundation Limited. + Copyright (C) 2000 Farm9. + Copyright (C) 2001 Frank Knobbe. + All rights reserved. + +For Cryptix code: + Use, modification, copying and distribution of this software is subject + the terms and conditions of the Cryptix General Licence. + + Cryptix General License + +Copyright (c) 1995 -2005 The Cryptix Foundation Limited. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + 1. Redistributions of source code must retain the copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + +THIS SOFTWARE IS PROVIDED BY THE CRYPTIX FOUNDATION LIMITED AND +CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE CRYPTIX FOUNDATION LIMITED OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The Files: + + minilzo.c + minilzo.h + lzodefs.h + +Copyright (C) 1996 - 2005 Markus Franz Xaver Johannes Oberhumer + +These file are part of the LZO real-time data compression library. + + All Rights Reserved. + + The LZO library is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + The LZO 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with the LZO library; see the file COPYING. + If not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + diff --git a/debian/dirs b/debian/dirs new file mode 100644 index 0000000..ca882bb --- /dev/null +++ b/debian/dirs @@ -0,0 +1,2 @@ +usr/bin +usr/sbin diff --git a/debian/docs b/debian/docs new file mode 100644 index 0000000..e845566 --- /dev/null +++ b/debian/docs @@ -0,0 +1 @@ +README diff --git a/debian/patches/01-edge.8.diff b/debian/patches/01-edge.8.diff new file mode 100644 index 0000000..0194e87 --- /dev/null +++ b/debian/patches/01-edge.8.diff @@ -0,0 +1,8 @@ +--- a/edge.8.old 2008-12-02 20:33:54.000000000 -0500 ++++ b/edge.8 2008-12-02 20:34:13.000000000 -0500 +@@ -1,4 +1,4 @@ +-.TH edge 1 "May 3, 2008" "revision 3472" "SUPERUSER COMMANDS" ++.TH edge 8 "May 3, 2008" "revision 3472" "SUPERUSER COMMANDS" + .SH NAME + edge \- n2n edge node daemon + .SH SYNOPSIS diff --git a/debian/patches/series b/debian/patches/series new file mode 100644 index 0000000..a92f0fe --- /dev/null +++ b/debian/patches/series @@ -0,0 +1 @@ +01-edge.8.diff diff --git a/debian/rules b/debian/rules new file mode 100755 index 0000000..5494adf --- /dev/null +++ b/debian/rules @@ -0,0 +1,79 @@ +#!/usr/bin/make -f +# -*- makefile -*- +# Uncomment this to turn on verbose mode. +#export DH_VERBOSE=1 + + +include /usr/share/quilt/quilt.make + +CFLAGS = -Wall -g + +ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS))) + CFLAGS += -O0 +else + CFLAGS += -O2 +endif + +configure: configure-stamp +configure-stamp: + dh_testdir + # Add here commands to configure the package. + + touch configure-stamp + + +build: patch build-stamp + +build-stamp: configure-stamp + dh_testdir + + # Add here commands to compile the package. + $(MAKE) + #docbook-to-man debian/n2n.sgml > n2n.1 + + touch $@ + +clean: unpatch + dh_testdir + dh_testroot + rm -f build-stamp configure-stamp + + # Add here commands to clean up after the build process. + [ ! -f Makefile ] || $(MAKE) clean + + dh_clean + +install: build + dh_testdir + dh_testroot + dh_clean -k + dh_installdirs + + # Add here commands to install the package into debian/n2n. + $(MAKE) DESTDIR=$(CURDIR)/debian/n2n install + + +# Build architecture-independent files here. +binary-indep: build install +# We have nothing to do by default. + +# Build architecture-dependent files here. +binary-arch: build install + dh_testdir + dh_testroot + dh_installchangelogs + dh_installdocs + dh_installexamples + dh_installman supernode.1 edge.8 + dh_link + dh_strip + dh_compress + dh_fixperms + dh_installdeb + dh_shlibdeps + dh_gencontrol + dh_md5sums + dh_builddeb + +binary: binary-indep binary-arch +.PHONY: build clean binary-indep binary-arch binary install configure diff --git a/edge.8 b/edge.8 new file mode 100644 index 0000000..a5f400c --- /dev/null +++ b/edge.8 @@ -0,0 +1,77 @@ +.TH edge 1 "May 3, 2008" "revision 3472" "SUPERUSER COMMANDS" +.SH NAME +edge \- n2n edge node daemon +.SH SYNOPSIS +.B edge +[\-d ] \-a \-c \-k \-l +[\-p ] [\-u ] [\-g ] [-f] [\-m ] [\-t] [\-r] [\-v] +.SH DESCRIPTION +N2N is a peer-to-peer VPN system. Edge is the edge node daemon for n2n which +creates a TAP interface to expose the n2n virtual LAN. On startup n2n creates +the TAP interface and configures it then registers with the supernode so it can +begin to find other nodes in the community. +.PP +.SH OPTIONS +.TP +\-d +sets the TAP device name as seen in ifconfig. +.TP +\-a +sets the n2n LAN IP address being claimed. +.TP +\-c +sets the n2n community name. +.TP +\-k +sets the twofish encryption key from ASCII text (see also N2N_KEY in ENVIRONMENT) +.TP +\-l +sets the n2n supernode IP address and port to register to +.TP +\-p +binds to the given UDP port +.TP +\-u +causes the edge process to drop to the given user ID when privileges are no longer required +.TP +\-g +causes the edge process to drop to the given group ID when privileges are no longer required +.TP +\-f +causes the edge process to fork and run as a daemon, closing stdin, stdout, stderr and becoming a process group leader +.TP +\-m +start the TAP interface with the given MAC address. This is highly recommended +as it means the same address will be used if edge stops and restarts. If this is +not done, the ARP caches of all peers will be wrong and packets will not flow to +this edge until the next ARP refresh. +.TP +\-t +use HTTP tunneling instead of the normal UDP mechanism (experimental) +.TP +\-r +all packet forwarding/routing through the n2n virtual LAN +.TP +\-v +use verbose logging +.SH ENVIRONMENT +.TP +.B N2N_KEY +set the encryption key so it is not visible on the command line +.SH EXAMPLES +.TP +.B edge \-d n2n0 \-c mynetwork \-k encryptme \-u 99 \-g 99 \-m DE:AD:BE:EF:01:23 \-a 192.168.254.7 \-l 123.121.120.119:7654 + +Start edge with TAP device n2n0 on community "mynetwork" with community +supernode at 123.121.120.119 UDP port 7654. Use "encryptme" as the shared +encryption key. Assign MAC address DE:AD:BE:EF:01:23 to the n2n interface and +drop to user=99 and group=99 after the TAP device is successfull configured. +.PP +Add the -f option to make it run as a daemon +.PP +.SH EXIT STATUS +edge is a daemon and any exit is an error +.SH AUTHOR +Luca Deri ( deri (at) ntop.org ), Richard Andrews ( andrews (at) ntop.org ), Don Bindner +.SH SEE ALSO +ifconfig(1) supernode(1) tunctl(1) diff --git a/edge.c b/edge.c new file mode 100644 index 0000000..2a67ef7 --- /dev/null +++ b/edge.c @@ -0,0 +1,1407 @@ +/* + * (C) 2007-09 - Luca Deri + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not see see + * + * Code contributions courtesy of: + * Richard Andrews + * Don Bindner + * + */ + +#include "minilzo.h" +#include "n2n.h" +#include +#include + +/** Time between logging system STATUS messages */ +#define STATUS_UPDATE_INTERVAL (30 * 60) /*secs*/ + +/* maximum length of command line arguments */ +#define MAX_CMDLINE_BUFFER_LENGTH 4096 +/* maximum length of a line in the configuration file */ +#define MAX_CONFFILE_LINE_LENGTH 1024 + +struct n2n_edge +{ + u_char re_resolve_supernode_ip; + struct peer_addr supernode; + char supernode_ip[48]; + char * community_name /*= NULL*/; + + /* int sock; */ + /* char is_udp_socket /\*= 1*\/; */ + n2n_sock_info_t sinfo; + + u_int pkt_sent /*= 0*/; + tuntap_dev device; + int allow_routing /*= 0*/; + int drop_ipv6_ndp /*= 0*/; + char * encrypt_key /* = NULL*/; + TWOFISH * tf; + + struct peer_info * known_peers /* = NULL*/; + struct peer_info * pending_peers /* = NULL*/; + time_t last_register /* = 0*/; +}; + +static void supernode2addr(n2n_edge_t * eee, char* addr); + +static void send_packet2net(n2n_edge_t * eee, + char *decrypted_msg, size_t len); + + +/* ************************************** */ + +/* parse the configuration file */ +static int readConfFile(const char * filename, char * const linebuffer) { + struct stat stats; + FILE * fd; + char * buffer = NULL; + + buffer = (char *)malloc(MAX_CONFFILE_LINE_LENGTH); + if (!buffer) { + traceEvent( TRACE_ERROR, "Unable to allocate memory"); + return -1; + } + + if (stat(filename, &stats)) { + if (errno == ENOENT) + traceEvent(TRACE_ERROR, "parameter file %s not found/unable to access\n", filename); + else + traceEvent(TRACE_ERROR, "cannot stat file %s, errno=%d\n",filename, errno); + free(buffer); + return -1; + } + + fd = fopen(filename, "rb"); + if (!fd) { + traceEvent(TRACE_ERROR, "Unable to open parameter file '%s' (%d)...\n",filename,errno); + free(buffer); + return -1; + } + while(fgets(buffer, MAX_CONFFILE_LINE_LENGTH,fd)) { + char * p = NULL; + + /* strip out comments */ + p = strchr(buffer, '#'); + if (p) *p ='\0'; + + /* remove \n */ + p = strchr(buffer, '\n'); + if (p) *p ='\0'; + + /* strip out heading spaces */ + p = buffer; + while(*p == ' ' && *p != '\0') ++p; + if (p != buffer) strncpy(buffer,p,strlen(p)+1); + + /* strip out trailing spaces */ + while(strlen(buffer) && buffer[strlen(buffer)-1]==' ') + buffer[strlen(buffer)-1]= '\0'; + + /* check for nested @file option */ + if (strchr(buffer, '@')) { + traceEvent(TRACE_ERROR, "@file in file nesting is not supported\n"); + free(buffer); + return -1; + } + if ((strlen(linebuffer)+strlen(buffer)+2)< MAX_CMDLINE_BUFFER_LENGTH) { + strncat(linebuffer, " ", 1); + strncat(linebuffer, buffer, strlen(buffer)); + } else { + traceEvent(TRACE_ERROR, "too many argument"); + free(buffer); + return -1; + } + } + + free(buffer); + fclose(fd); + + return 0; +} + +/* Create the argv vector */ +static char ** buildargv(char * const linebuffer) { + const int INITIAL_MAXARGC = 16; /* Number of args + NULL in initial argv */ + int maxargc; + int argc=0; + char ** argv; + char * buffer, * buff; + + buffer = (char *)malloc(strlen(linebuffer)+2); + if (!buffer) { + traceEvent( TRACE_ERROR, "Unable to allocate memory"); + return NULL; + } + strncpy(buffer, linebuffer,strlen(linebuffer)); + + maxargc = INITIAL_MAXARGC; + argv = (char **)malloc(maxargc * sizeof(char*)); + if (argv == NULL) { + traceEvent( TRACE_ERROR, "Unable to allocate memory"); + return NULL; + } + buff = buffer; + while(buff) { + char * p = strchr(buff,' '); + if (p) { + *p='\0'; + argv[argc++] = strdup(buff); + while(*++p == ' ' && *p != '\0'); + buff=p; + if (argc >= maxargc) { + maxargc *= 2; + argv = (char **)realloc(argv, maxargc * sizeof(char*)); + if (argv == NULL) { + traceEvent(TRACE_ERROR, "Unable to re-allocate memory"); + free(buffer); + return NULL; + } + } + } else { + argv[argc++] = strdup(buff); + break; + } + } + argv[argc] = NULL; + free(buffer); + return argv; +} + + + +/* ************************************** */ + +static int edge_init(n2n_edge_t * eee) { +#ifdef WIN32 + initWin32(); +#endif + memset(eee, 0, sizeof(n2n_edge_t)); + + eee->re_resolve_supernode_ip = 0; + eee->community_name = NULL; + eee->sinfo.sock = -1; + eee->sinfo.is_udp_socket = 1; + eee->pkt_sent = 0; + eee->allow_routing = 0; + eee->drop_ipv6_ndp = 0; + eee->encrypt_key = NULL; + eee->tf = NULL; + eee->known_peers = NULL; + eee->pending_peers = NULL; + eee->last_register = 0; + + if(lzo_init() != LZO_E_OK) { + traceEvent(TRACE_ERROR, "LZO compression error"); + return(-1); + } + + return(0); +} + +static int edge_init_twofish( n2n_edge_t * eee, u_int8_t *encrypt_pwd, u_int32_t encrypt_pwd_len ) +{ + eee->tf = TwoFishInit(encrypt_pwd, encrypt_pwd_len); + + if ( eee->tf ) + { + return 0; + } + else + { + return 1; + } +} + +/* ************************************** */ + +static void edge_deinit(n2n_edge_t * eee) { + TwoFishDestroy(eee->tf); + if ( eee->sinfo.sock >=0 ) + { + close( eee->sinfo.sock ); + } +} + +static void readFromIPSocket( n2n_edge_t * eee ); + +static void help() { + print_n2n_version(); + + printf("edge " +#ifdef __linux__ + "-d " +#endif + "-a " + "-c " + "-k " +#ifndef WIN32 + "[-u -g ]" + "[-f]" +#endif + "[-m ]" + "\n" + "-l " + "[-p ] " + "[-t] [-r] [-v] [-b] [-h]\n\n"); + +#ifdef __linux__ + printf("-d | tun device name\n"); +#endif + + printf("-a | n2n IP address\n"); + printf("-c | n2n community name\n"); + printf("-k | Encryption key (ASCII) - also N2N_KEY=\n"); + printf("-l | Supernode IP:port\n"); + printf("-b | Periodically resolve supernode IP\n"); + printf(" | (when supernodes are running on dynamic IPs)\n"); + printf("-p | Local port used for connecting to supernode\n"); +#ifndef WIN32 + printf("-u | User ID (numeric) to use when privileges are dropped\n"); + printf("-g | Group ID (numeric) to use when privileges are dropped\n"); + printf("-f | Fork and run as a daemon. Use syslog.\n"); +#endif + printf("-m | Choose a MAC address for the TAP interface\n" + " | eg. -m 01:02:03:04:05:06\n"); + printf("-t | Use http tunneling (experimental)\n"); + printf("-r | Enable packet forwarding through n2n community\n"); + printf("-v | Verbose\n"); + + printf("\nEnvironment variables:\n"); + printf(" N2N_KEY | Encryption key (ASCII)\n" ); + + exit(0); +} + +/* *********************************************** */ + + +static void send_register( n2n_edge_t * eee, + const struct peer_addr *remote_peer, + u_char is_ack) { + struct n2n_packet_header hdr; + char pkt[N2N_PKT_HDR_SIZE]; + size_t len = sizeof(hdr); + ipstr_t ip_buf; + + fill_standard_header_fields( &(eee->sinfo), &hdr, (char*)(eee->device.mac_addr)); + hdr.sent_by_supernode = 0; + hdr.msg_type = (is_ack == 0) ? MSG_TYPE_REGISTER : MSG_TYPE_REGISTER_ACK; + memcpy(hdr.community_name, eee->community_name, COMMUNITY_LEN); + + marshall_n2n_packet_header( (u_int8_t *)pkt, &hdr ); + send_packet( &(eee->sinfo), pkt, &len, remote_peer, 1 ); + + traceEvent(TRACE_INFO, "Sent %s message to %s:%d", + ((hdr.msg_type==MSG_TYPE_REGISTER)?"MSG_TYPE_REGISTER":"MSG_TYPE_REGISTER_ACK"), + intoa(ntohl(remote_peer->addr_type.v4_addr), ip_buf, sizeof(ip_buf)), + ntohs(remote_peer->port)); +} + +/* *********************************************** */ + +static void send_deregister(n2n_edge_t * eee, + struct peer_addr *remote_peer) { + struct n2n_packet_header hdr; + char pkt[N2N_PKT_HDR_SIZE]; + size_t len = sizeof(hdr); + + fill_standard_header_fields( &(eee->sinfo), &hdr, (char*)(eee->device.mac_addr) ); + hdr.sent_by_supernode = 0; + hdr.msg_type = MSG_TYPE_DEREGISTER; + memcpy(hdr.community_name, eee->community_name, COMMUNITY_LEN); + + marshall_n2n_packet_header( (u_int8_t *)pkt, &hdr ); + send_packet( &(eee->sinfo), pkt, &len, remote_peer, 1); +} + +/* *********************************************** */ + +static void update_peer_address(n2n_edge_t * eee, + const struct n2n_packet_header * hdr, + time_t when); +void trace_registrations( struct peer_info * scan ); +int is_ip6_discovery( const void * buf, size_t bufsize ); +void check_peer( n2n_edge_t * eee, + const struct n2n_packet_header * hdr ); +void try_send_register( n2n_edge_t * eee, + const struct n2n_packet_header * hdr ); +void set_peer_operational( n2n_edge_t * eee, const struct n2n_packet_header * hdr ); + + + +/** Start the registration process. + * + * If the peer is already in pending_peers, ignore the request. + * If not in pending_peers, add it and send a REGISTER. + * + * If hdr is for a direct peer-to-peer packet, try to register back to sender + * even if the MAC is in pending_peers. This is because an incident direct + * packet indicates that peer-to-peer exchange should work so more aggressive + * registration can be permitted (once per incoming packet) as this should only + * last for a small number of packets.. + * + * Called from the main loop when Rx a packet for our device mac. + */ +void try_send_register( n2n_edge_t * eee, + const struct n2n_packet_header * hdr ) +{ + ipstr_t ip_buf; + + /* REVISIT: purge of pending_peers not yet done. */ + struct peer_info * scan = find_peer_by_mac( eee->pending_peers, hdr->src_mac ); + + if ( NULL == scan ) + { + scan = calloc( 1, sizeof( struct peer_info ) ); + + memcpy(scan->mac_addr, hdr->src_mac, 6); + scan->public_ip = hdr->public_ip; + scan->last_seen = time(NULL); /* Don't change this it marks the pending peer for removal. */ + + peer_list_add( &(eee->pending_peers), scan ); + + traceEvent( TRACE_NORMAL, "Pending peers list size=%ld", + peer_list_size( eee->pending_peers ) ); + + traceEvent( TRACE_NORMAL, "Sending REGISTER request to %s:%d", + intoa(ntohl(scan->public_ip.addr_type.v4_addr), ip_buf, sizeof(ip_buf)), + ntohs(scan->public_ip.port)); + + send_register(eee, + &(scan->public_ip), + 0 /* is not ACK */ ); + + /* pending_peers now owns scan. */ + } + else + { + /* scan already in pending_peers. */ + + if ( 0 == hdr->sent_by_supernode ) + { + /* over-write supernode-based socket with direct socket. */ + scan->public_ip = hdr->public_ip; + + traceEvent( TRACE_NORMAL, "Sending additional REGISTER request to %s:%d", + intoa(ntohl(scan->public_ip.addr_type.v4_addr), ip_buf, sizeof(ip_buf)), + ntohs(scan->public_ip.port)); + + + send_register(eee, + &(scan->public_ip), + 0 /* is not ACK */ ); + } + } +} + + +/** Update the last_seen time for this peer, or get registered. */ +void check_peer( n2n_edge_t * eee, + const struct n2n_packet_header * hdr ) +{ + struct peer_info * scan = find_peer_by_mac( eee->known_peers, hdr->src_mac ); + + if ( NULL == scan ) + { + /* Not in known_peers - start the REGISTER process. */ + try_send_register( eee, hdr ); + } + else + { + /* Already in known_peers. */ + update_peer_address( eee, hdr, time(NULL) ); + } +} + + +/* Move the peer from the pending_peers list to the known_peers lists. + * + * peer must be a pointer to an element of the pending_peers list. + * + * Called by main loop when Rx a REGISTER_ACK. + */ +void set_peer_operational( n2n_edge_t * eee, const struct n2n_packet_header * hdr ) +{ + struct peer_info * prev = NULL; + struct peer_info * scan; + macstr_t mac_buf; + ipstr_t ip_buf; + + scan=eee->pending_peers; + + while ( NULL != scan ) + { + if ( 0 != memcmp( scan->mac_addr, hdr->dst_mac, 6 ) ) + { + break; /* found. */ + } + + prev = scan; + scan = scan->next; + } + + if ( scan ) + { + + /* Remove scan from pending_peers. */ + if ( prev ) + { + prev->next = scan->next; + } + else + { + eee->pending_peers = scan->next; + } + + /* Add scan to known_peers. */ + scan->next = eee->known_peers; + eee->known_peers = scan; + + scan->public_ip = hdr->public_ip; + + traceEvent(TRACE_INFO, "=== new peer [mac=%s][socket=%s:%d]", + macaddr_str(scan->mac_addr, mac_buf, sizeof(mac_buf)), + intoa(ntohl(scan->public_ip.addr_type.v4_addr), ip_buf, sizeof(ip_buf)), + ntohs(scan->public_ip.port)); + + traceEvent( TRACE_NORMAL, "Pending peers list size=%ld", + peer_list_size( eee->pending_peers ) ); + + traceEvent( TRACE_NORMAL, "Operational peers list size=%ld", + peer_list_size( eee->known_peers ) ); + + + scan->last_seen = time(NULL); + } + else + { + traceEvent( TRACE_WARNING, "Failed to find sender in pending_peers." ); + } +} + + +void trace_registrations( struct peer_info * scan ) +{ + macstr_t mac_buf; + ipstr_t ip_buf; + + while ( scan ) + { + traceEvent(TRACE_INFO, "=== peer [mac=%s][socket=%s:%d]", + macaddr_str(scan->mac_addr, mac_buf, sizeof(mac_buf)), + intoa(ntohl(scan->public_ip.addr_type.v4_addr), ip_buf, sizeof(ip_buf)), + ntohs(scan->public_ip.port)); + + scan = scan->next; + } + +} + +u_int8_t broadcast_mac[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; + + +/** Keep the known_peers list straight. + * + * Ignore broadcast L2 packets, and packets with invalid public_ip. + * If the dst_mac is in known_peers make sure the entry is correct: + * - if the public_ip socket has changed, erase the entry + * - if the same, update its last_seen = when + */ +static void update_peer_address(n2n_edge_t * eee, + const struct n2n_packet_header * hdr, + time_t when) +{ + ipstr_t ip_buf; + struct peer_info *scan = eee->known_peers; + struct peer_info *prev = NULL; /* use to remove bad registrations. */ + + if ( 0 == hdr->public_ip.addr_type.v4_addr ) + { + /* Not to be registered. */ + return; + } + + if ( 0 == memcmp( hdr->dst_mac, broadcast_mac, 6 ) ) + { + /* Not to be registered. */ + return; + } + + + while(scan != NULL) + { + if(memcmp(hdr->dst_mac, scan->mac_addr, 6) == 0) + { + break; + } + + prev = scan; + scan = scan->next; + } + + if ( NULL == scan ) + { + /* Not in known_peers. */ + return; + } + + if ( 0 != memcmp( &(scan->public_ip), &(hdr->public_ip), sizeof(struct peer_addr))) + { + if ( 0 == hdr->sent_by_supernode ) + { + traceEvent( TRACE_NORMAL, "Peer changed public socket, Was %s:%d", + intoa(ntohl(hdr->public_ip.addr_type.v4_addr), ip_buf, sizeof(ip_buf)), + ntohs(hdr->public_ip.port)); + + /* The peer has changed public socket. It can no longer be assumed to be reachable. */ + /* Remove the peer. */ + if ( NULL == prev ) + { + /* scan was head of list */ + eee->known_peers = scan->next; + } + else + { + prev->next = scan->next; + } + free(scan); + + try_send_register( eee, hdr ); + } + else + { + /* Don't worry about what the supernode reports, it could be seeing a different socket. */ + } + } + else + { + /* Found and unchanged. */ + scan->last_seen = when; + } +} + + + +#if defined(DUMMY_ID_00001) /* Disabled waiting for config option to enable it */ + +/* *********************************************** */ + +static char gratuitous_arp[] = { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* Dest mac */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Src mac */ + 0x08, 0x06, /* ARP */ + 0x00, 0x01, /* Ethernet */ + 0x08, 0x00, /* IP */ + 0x06, /* Hw Size */ + 0x04, /* Protocol Size */ + 0x00, 0x01, /* ARP Request */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Src mac */ + 0x00, 0x00, 0x00, 0x00, /* Src IP */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Target mac */ + 0x00, 0x00, 0x00, 0x00 /* Target IP */ +}; + +static int build_gratuitous_arp(char *buffer, u_short buffer_len) { + if(buffer_len < sizeof(gratuitous_arp)) return(-1); + + memcpy(buffer, gratuitous_arp, sizeof(gratuitous_arp)); + memcpy(&buffer[6], device.mac_addr, 6); + memcpy(&buffer[22], device.mac_addr, 6); + memcpy(&buffer[28], &device.ip_addr, 4); + + /* REVISIT: BbMaj7 - use a real netmask here. This is valid only by accident + * for /24 IPv4 networks. */ + buffer[31] = 0xFF; /* Use a faked broadcast address */ + memcpy(&buffer[38], &device.ip_addr, 4); + return(sizeof(gratuitous_arp)); +} + +/** Called from update_registrations to periodically send gratuitous ARP + * broadcasts. */ +static void send_grat_arps(n2n_edge_t * eee,) { + char buffer[48]; + size_t len; + + traceEvent(TRACE_NORMAL, "Sending gratuitous ARP..."); + len = build_gratuitous_arp(buffer, sizeof(buffer)); + send_packet2net(eee, buffer, len); + send_packet2net(eee, buffer, len); /* Two is better than one :-) */ +} +#endif /* #if defined(DUMMY_ID_00001) */ + + + +/* *********************************************** */ + +/** @brief Check to see if we should re-register with our peers and the + * supernode. + * + * This is periodically called by the main loop. The list of registrations is + * not modified. Registration packets may be sent. + */ +static void update_registrations( n2n_edge_t * eee ) { + /* REVISIT: BbMaj7: have shorter timeout to REGISTER to supernode if this has + * not yet succeeded. */ + + if(time(NULL) < (eee->last_register+REGISTER_FREQUENCY)) return; /* Too early */ + + traceEvent(TRACE_NORMAL, "Registering with supernode"); + if(eee->re_resolve_supernode_ip) + supernode2addr(eee, eee->supernode_ip); + + send_register(eee, &(eee->supernode), 0); /* Register with supernode */ + + /* REVISIT: turn-on gratuitous ARP with config option. */ + /* send_grat_arps(sock_fd, is_udp_sock); */ + + eee->last_register = time(NULL); +} + +/* ***************************************************** */ + +static int find_peer_destination(n2n_edge_t * eee, + const u_char *mac_address, + struct peer_addr *destination) { + const struct peer_info *scan = eee->known_peers; + macstr_t mac_buf; + ipstr_t ip_buf; + int retval=0; + + traceEvent(TRACE_INFO, "Searching destination peer for MAC %02X:%02X:%02X:%02X:%02X:%02X", + mac_address[0] & 0xFF, mac_address[1] & 0xFF, mac_address[2] & 0xFF, + mac_address[3] & 0xFF, mac_address[4] & 0xFF, mac_address[5] & 0xFF); + + while(scan != NULL) { + traceEvent(TRACE_INFO, "Evaluating peer [MAC=%02X:%02X:%02X:%02X:%02X:%02X][ip=%s:%d]", + scan->mac_addr[0] & 0xFF, scan->mac_addr[1] & 0xFF, scan->mac_addr[2] & 0xFF, + scan->mac_addr[3] & 0xFF, scan->mac_addr[4] & 0xFF, scan->mac_addr[5] & 0xFF, + intoa(ntohl(scan->public_ip.addr_type.v4_addr), ip_buf, sizeof(ip_buf)), + ntohs(scan->public_ip.port)); + + if((scan->last_seen > 0) && + (memcmp(mac_address, scan->mac_addr, 6) == 0)) + { + memcpy(destination, &scan->public_ip, sizeof(struct sockaddr_in)); + retval=1; + break; + } + scan = scan->next; + } + + if ( 0 == retval ) + { + memcpy(destination, &(eee->supernode), sizeof(struct sockaddr_in)); + } + + traceEvent(TRACE_INFO, "find_peer_address(%s) -> [socket=%s:%d]", + macaddr_str( (char *)mac_address, mac_buf, sizeof(mac_buf)), + intoa(ntohl(destination->addr_type.v4_addr), ip_buf, sizeof(ip_buf)), + ntohs(destination->port)); + + return retval; +} + +/* *********************************************** */ + +static const struct option long_options[] = { + { "community", required_argument, NULL, 'c' }, + { "supernode-list", required_argument, NULL, 'l' }, + { "tun-device", required_argument, NULL, 'd' }, + { "euid", required_argument, NULL, 'u' }, + { "egid", required_argument, NULL, 'g' }, + { "help" , no_argument, NULL, 'h' }, + { "verbose", no_argument, NULL, 'v' }, + { NULL, 0, NULL, 0 } +}; + +/* ***************************************************** */ + + +/** A layer-2 packet was received at the tunnel and needs to be sent via UDP. */ +static void send_packet2net(n2n_edge_t * eee, + char *decrypted_msg, size_t len) { + ipstr_t ip_buf; + char packet[2048]; + int data_sent_len; + struct n2n_packet_header hdr; + struct peer_addr destination; + macstr_t mac_buf; + macstr_t mac2_buf; + struct ether_header *eh = (struct ether_header*)decrypted_msg; + + /* Discard IP packets that are not originated by this hosts */ + if(!(eee->allow_routing)) { + if(ntohs(eh->ether_type) == 0x0800) { + + /* This is an IP packet from the local source address - not forwarded. */ +#define ETH_FRAMESIZE 14 +#define IP4_SRCOFFSET 12 +#define IP4_ADDRSIZE 4 + /* Note: all elements of the_ip are in network order */ + if( 0 != memcmp( decrypted_msg + ETH_FRAMESIZE + IP4_SRCOFFSET, + &(eee->device.ip_addr), + IP4_ADDRSIZE ) ) { + /* This is a packet that needs to be routed */ + traceEvent(TRACE_INFO, "Discarding routed packet"); + return; + } else { + /* This packet is originated by us */ + /* traceEvent(TRACE_INFO, "Sending non-routed packet"); */ + } + } + } + + /* Encrypt "decrypted_msg" into the second half of the n2n packet. */ + len = TwoFishEncryptRaw((u_int8_t *)decrypted_msg, + (u_int8_t *)&packet[N2N_PKT_HDR_SIZE], len, eee->tf); + + /* Add the n2n header to the start of the n2n packet. */ + fill_standard_header_fields( &(eee->sinfo), &hdr, (char*)(eee->device.mac_addr) ); + hdr.msg_type = MSG_TYPE_PACKET; + hdr.sent_by_supernode = 0; + memcpy(hdr.community_name, eee->community_name, COMMUNITY_LEN); + memcpy(hdr.dst_mac, decrypted_msg, 6); + + marshall_n2n_packet_header( (u_int8_t *)packet, &hdr ); + + len += N2N_PKT_HDR_SIZE; + + if(find_peer_destination(eee, eh->ether_dhost, &destination)) + traceEvent(TRACE_INFO, "** Going direct [dst_mac=%s][dest=%s:%d]", + macaddr_str((char*)eh->ether_dhost, mac_buf, sizeof(mac_buf)), + intoa(ntohl(destination.addr_type.v4_addr), ip_buf, sizeof(ip_buf)), + ntohs(destination.port)); + else + traceEvent(TRACE_INFO, " Going via supernode [src_mac=%s][dst_mac=%s]", + macaddr_str((char*)eh->ether_shost, mac_buf, sizeof(mac_buf)), + macaddr_str((char*)eh->ether_dhost, mac2_buf, sizeof(mac2_buf))); + + data_sent_len = reliable_sendto( &(eee->sinfo), packet, &len, &destination, 1); + + if(data_sent_len != len) + traceEvent(TRACE_WARNING, "sendto() [sent=%d][attempted_to_send=%d] [%s]\n", + data_sent_len, len, strerror(errno)); + else { + ++(eee->pkt_sent); + traceEvent(TRACE_INFO, "Sent %d byte MSG_TYPE_PACKET ok", data_sent_len); + } +} + +/* ***************************************************** */ + +/** Destination MAC 33:33:0:00:00:00 - 33:33:FF:FF:FF:FF is reserved for IPv6 + * neighbour discovery. + */ +int is_ip6_discovery( const void * buf, size_t bufsize ) +{ + int retval = 0; + + if ( bufsize >= sizeof(struct ether_header) ) + { + struct ether_header *eh = (struct ether_header*)buf; + if ( (0x33 == eh->ether_dhost[0]) && + (0x33 == eh->ether_dhost[1]) ) + { + retval = 1; /* This is an IPv6 neighbour discovery packet. */ + } + } + return retval; +} + + +/* ***************************************************** */ + +/* + * Return: 0 = ok, -1 = invalid packet + * + */ +static int check_received_packet(n2n_edge_t * eee, char *pkt, + u_int pkt_len) { + + if(pkt_len == 42) { + /* ARP */ + if((pkt[12] != 0x08) || (pkt[13] != 0x06)) return(0); /* No ARP */ + if((pkt[20] != 0x00) || (pkt[21] != 0x02)) return(0); /* No ARP Reply */ + if(memcmp(&pkt[28], &(eee->device.ip_addr), 4)) return(0); /* This is not me */ + + if(memcmp(eee->device.mac_addr, &pkt[22], 6) == 0) { + traceEvent(TRACE_WARNING, "Bounced packet received: supernode bug?"); + return(0); + } + + traceEvent(TRACE_ERROR, "Duplicate address found. Your IP is used by MAC %02X:%02X:%02X:%02X:%02X:%02X", + pkt[22+0] & 0xFF, pkt[22+1] & 0xFF, pkt[22+2] & 0xFF, + pkt[22+3] & 0xFF, pkt[22+4] & 0xFF, pkt[22+5] & 0xFF); + exit(0); + } else if(pkt_len > 32 /* IP + Ethernet */) { + /* Check if this packet is for us or if it's routed */ + struct ether_header *eh = (struct ether_header*)pkt; + + if(ntohs(eh->ether_type) == 0x0800) { + + /* Note: all elements of the_ip are in network order */ + struct ip *the_ip = (struct ip*)(pkt+sizeof(struct ether_header)); + + if((the_ip->ip_dst.s_addr != eee->device.ip_addr) + && ((the_ip->ip_dst.s_addr & eee->device.device_mask) != (eee->device.ip_addr & eee->device.device_mask))) /* Not a broadcast */ + { + ipstr_t ip_buf; + ipstr_t ip_buf2; + + /* This is a packet that needs to be routed */ + traceEvent(TRACE_INFO, "Discarding routed packet [rcvd=%s][expected=%s]", + intoa(ntohl(the_ip->ip_dst.s_addr), ip_buf, sizeof(ip_buf)), + intoa(ntohl(eee->device.ip_addr), ip_buf2, sizeof(ip_buf2))); + } else { + /* This packet is for us */ + + /* traceEvent(TRACE_INFO, "Received non-routed packet"); */ + return(0); + } + } else + return(0); + } else { + traceEvent(TRACE_INFO, "Packet too short (%d bytes): discarded", pkt_len); + } + + return(-1); +} + +/* ***************************************************** */ + +/** Read a single packet from the TAP interface, process it and write out the + * corresponding packet to the cooked socket. + * + * REVISIT: fails if more than one packet is waiting to be read. + */ +static void readFromTAPSocket( n2n_edge_t * eee ) +{ + /* tun -> remote */ + u_char decrypted_msg[2048]; + size_t len; + + len = tuntap_read(&(eee->device), decrypted_msg, sizeof(decrypted_msg)); + + if((len <= 0) || (len > sizeof(decrypted_msg))) + traceEvent(TRACE_WARNING, "read()=%d [%d/%s]\n", + len, errno, strerror(errno)); + else { + traceEvent(TRACE_INFO, "### Rx L2 Msg (%d) tun -> network", len); + + if ( eee->drop_ipv6_ndp && is_ip6_discovery( decrypted_msg, len ) ) { + traceEvent(TRACE_WARNING, "Dropping unsupported IPv6 neighbour discovery packet"); + } else { + send_packet2net(eee, (char*)decrypted_msg, len); + } + } +} + +/* ***************************************************** */ + + +void readFromIPSocket( n2n_edge_t * eee ) +{ + ipstr_t ip_buf; + macstr_t mac_buf; + char packet[2048], decrypted_msg[2048]; + size_t len; + int data_sent_len; + struct peer_addr sender; + + /* remote -> tun */ + u_int8_t discarded_pkt; + struct n2n_packet_header hdr_storage; + + len = receive_data( &(eee->sinfo), packet, sizeof(packet), &sender, + &discarded_pkt, (char*)(eee->device.mac_addr), 1, &hdr_storage); + + if(len <= 0) return; + + traceEvent(TRACE_INFO, "### Rx N2N Msg network -> tun"); + + if(discarded_pkt) { + traceEvent(TRACE_INFO, "Discarded incoming pkt"); + } else { + if(len <= 0) + traceEvent(TRACE_WARNING, "receive_data()=%d [%s]\n", len, strerror(errno)); + else { + if(len < N2N_PKT_HDR_SIZE) + traceEvent(TRACE_WARNING, "received packet too short [len=%d]\n", len); + else { + struct n2n_packet_header *hdr = &hdr_storage; + + traceEvent(TRACE_INFO, "Received packet from %s:%d", + intoa(ntohl(sender.addr_type.v4_addr), ip_buf, sizeof(ip_buf)), + ntohs(sender.port)); + + traceEvent(TRACE_INFO, "Received message [msg_type=%s] from %s [dst mac=%s]", + msg_type2str(hdr->msg_type), + hdr->sent_by_supernode ? "supernode" : "peer", + macaddr_str(hdr->dst_mac, mac_buf, sizeof(mac_buf))); + + if(hdr->version != N2N_VERSION) { + traceEvent(TRACE_WARNING, + "Received packet with unknown protocol version (%d): discarded\n", + hdr->version); + return; + } + + /* FIX - Add IPv6 support */ + if(hdr->public_ip.addr_type.v4_addr == 0) { + hdr->public_ip.addr_type.v4_addr = sender.addr_type.v4_addr; + hdr->public_ip.port = sender.port; + hdr->public_ip.family = AF_INET; + } + + if(strncmp(hdr->community_name, eee->community_name, COMMUNITY_LEN) != 0) { + traceEvent(TRACE_WARNING, "Received packet with invalid community [expected=%s][received=%s]\n", + eee->community_name, hdr->community_name); + } else { + if(hdr->msg_type == MSG_TYPE_PACKET) { + /* assert: the packet received is destined for device.mac_addr or broadcast MAC. */ + + len -= N2N_PKT_HDR_SIZE; + + /* Decrypt message first */ + len = TwoFishDecryptRaw((u_int8_t *)&packet[N2N_PKT_HDR_SIZE], + (u_int8_t *)decrypted_msg, len, eee->tf); + + if(len > 0) { + if(check_received_packet(eee, decrypted_msg, len) == 0) { + + if ( 0 == memcmp(hdr->dst_mac, eee->device.mac_addr, 6) ) + { + check_peer( eee, hdr ); + } + + data_sent_len = tuntap_write(&(eee->device), (u_char*)decrypted_msg, len); + + if(data_sent_len != len) + traceEvent(TRACE_WARNING, "tuntap_write() [sent=%d][attempted_to_send=%d] [%s]\n", + data_sent_len, len, strerror(errno)); + else { + /* Normal situation. */ + traceEvent(TRACE_INFO, "### Tx L2 Msg -> tun"); + } + } else { + traceEvent(TRACE_WARNING, "Bad destination: message discarded"); + } + } + /* else silently ignore empty packet. */ + + } else if(hdr->msg_type == MSG_TYPE_REGISTER) { + traceEvent(TRACE_INFO, "Received registration request from remote peer [ip=%s:%d]", + intoa(ntohl(hdr->public_ip.addr_type.v4_addr), ip_buf, sizeof(ip_buf)), + ntohs(hdr->public_ip.port)); + if ( 0 == memcmp(hdr->dst_mac, (eee->device.mac_addr), 6) ) + { + check_peer( eee, hdr ); + } + + + send_register(eee, &hdr->public_ip, 1); /* Send ACK back */ + } else if(hdr->msg_type == MSG_TYPE_REGISTER_ACK) { + traceEvent(TRACE_NORMAL, "Received REGISTER_ACK from remote peer [ip=%s:%d]", + intoa(ntohl(hdr->public_ip.addr_type.v4_addr), ip_buf, sizeof(ip_buf)), + ntohs(hdr->public_ip.port)); + + /* if ( 0 == memcmp(hdr->dst_mac, eee->device.mac_addr, 6) ) */ + { + if ( hdr->sent_by_supernode ) + { + /* Response to supernode registration. Supernode is not in the pending_peers list. */ + } + else + { + /* Move from pending_peers to known_peers; ignore if not in pending. */ + set_peer_operational( eee, hdr ); + } + } + + } else { + traceEvent(TRACE_WARNING, "Unable to handle packet type %d: ignored\n", hdr->msg_type); + return; + } + } + } + } + } +} + +/* ***************************************************** */ + + +#ifdef WIN32 +static DWORD tunReadThread(LPVOID lpArg ) +{ + n2n_edge_t *eee = (n2n_edge_t*)lpArg; + + while(1) { + readFromTAPSocket(eee); + } + + return((DWORD)NULL); +} + +/* ***************************************************** */ + +static void startTunReadThread(n2n_edge_t *eee) { + HANDLE hThread; + DWORD dwThreadId; + + hThread = CreateThread(NULL, /* no security attributes */ + 0, /* use default stack size */ + (LPTHREAD_START_ROUTINE)tunReadThread, /* thread function */ + (void*)eee, /* argument to thread function */ + 0, /* use default creation flags */ + &dwThreadId); /* returns the thread identifier */ +} +#endif + +/* ***************************************************** */ + +static void supernode2addr(n2n_edge_t * eee, char* addr) { + char *supernode_host = strtok(addr, ":"); + + if(supernode_host) { + char *supernode_port = strtok(NULL, ":"); + const struct addrinfo aihints = {0, PF_INET, 0, 0, 0, NULL, NULL, NULL}; + struct addrinfo * ainfo = NULL; + int nameerr; + ipstr_t ip_buf; + + if ( supernode_port ) + eee->supernode.port = htons(atoi(supernode_port)); + else + traceEvent(TRACE_WARNING, "Bad supernode parameter (-l )"); + + nameerr = getaddrinfo( supernode_host, NULL, &aihints, &ainfo ); + + if( 0 == nameerr ) + { + struct sockaddr_in * saddr; + + /* ainfo s the head of a linked list if non-NULL. */ + if ( ainfo && (PF_INET == ainfo->ai_family) ) + { + /* It is definitely and IPv4 address -> sockaddr_in */ + saddr = (struct sockaddr_in *)ainfo->ai_addr; + + eee->supernode.addr_type.v4_addr = saddr->sin_addr.s_addr; + } + else + { + /* Should only return IPv4 addresses due to aihints. */ + traceEvent(TRACE_WARNING, "Failed to resolve supernode IPv4 address for %s", supernode_host); + } + + freeaddrinfo(ainfo); /* free everything allocated by getaddrinfo(). */ + ainfo = NULL; + } else { + traceEvent(TRACE_WARNING, "Failed to resolve supernode host %s, assuming numeric", supernode_host); + eee->supernode.addr_type.v4_addr = inet_addr(supernode_host); + } + + traceEvent(TRACE_NORMAL, "Using supernode %s:%d", + intoa(ntohl(eee->supernode.addr_type.v4_addr), ip_buf, sizeof(ip_buf)), + ntohs(eee->supernode.port)); + } else + traceEvent(TRACE_WARNING, "Wrong supernode parameter (-l )"); +} + +/* ***************************************************** */ + +extern int useSyslog; + +int main(int argc, char* argv[]) { + int opt, local_port = 0 /* any port */; + char *tuntap_dev_name = "edge0"; + char *ip_addr = NULL; + +#ifndef WIN32 + uid_t userid=0; /* root is the only guaranteed ID */ + gid_t groupid=0; /* root is the only guaranteed ID */ + int fork_as_daemon=0; +#endif + + size_t numPurged; + time_t lastStatus=0; + + char * device_mac=NULL; + char * encrypt_key; + + int i, effectiveargc=0; + char ** effectiveargv=NULL; + char * linebuffer = NULL; + + n2n_edge_t eee; /* single instance for this program */ + + if (-1 == edge_init(&eee) ){ + traceEvent( TRACE_ERROR, "Failed in edge_init" ); + exit(1); + } + + if( getenv( "N2N_KEY" )) { + encrypt_key = strdup( getenv( "N2N_KEY" )); + } + +#ifdef WIN32 + tuntap_dev_name = ""; +#endif + memset(&(eee.supernode), 0, sizeof(eee.supernode)); + eee.supernode.family = AF_INET; + + linebuffer = (char *)malloc(MAX_CMDLINE_BUFFER_LENGTH); + if (!linebuffer) { + traceEvent( TRACE_ERROR, "Unable to allocate memory"); + exit(1); + } + snprintf(linebuffer, MAX_CMDLINE_BUFFER_LENGTH, "%s",argv[0]); + for(i=1;i COMMUNITY_LEN) + eee.community_name[COMMUNITY_LEN] = '\0'; + break; +#ifndef WIN32 + + case 'u': /* uid */ + { + userid=atoi(optarg); + break; + } + case 'g': /* uid */ + { + groupid=atoi(optarg); + break; + } + case 'f' : /* fork as daemon */ + { + fork_as_daemon=1; + break; + } +#endif + case 'm' : /* device_mac */ + { + device_mac=strdup(optarg); + break; + } + case 'k': /* encrypt key */ + encrypt_key = strdup(optarg); + break; + case 'r': /* enable packet routing across n2n endpoints */ + eee.allow_routing = 1; + break; + case 'l': /* supernode-list */ + snprintf(eee.supernode_ip, sizeof(eee.supernode_ip), "%s", optarg); + supernode2addr(&eee, eee.supernode_ip); + break; +#ifdef __linux__ + case 'd': /* tun-device */ + tuntap_dev_name = strdup(optarg); + break; +#endif + case 't': /* Use HTTP tunneling */ + eee.sinfo.is_udp_socket = 0; + break; + case 'b': + eee.re_resolve_supernode_ip = 1; + break; + case 'p': + local_port = atoi(optarg); + break; + case 'h': /* help */ + help(); + break; + case 'v': /* verbose */ + traceLevel = 3; + break; + } + } + + if(!( +#ifdef __linux__ + tuntap_dev_name && +#endif + eee.community_name && + ip_addr && + eee.supernode.addr_type.v4_addr && + encrypt_key)) + help(); + +#ifndef WIN32 + /* If running suid root then we need to setuid before using the force. */ + setuid( 0 ); + /* setgid( 0 ); */ +#endif + + if(tuntap_open(&(eee.device), tuntap_dev_name, ip_addr, "255.255.255.0", device_mac ) < 0) + return(-1); + +#ifndef WIN32 + if ( (userid != 0) || (groupid != 0 ) ) { + traceEvent(TRACE_NORMAL, "Interface up. Dropping privileges to uid=%d, gid=%d", userid, groupid); + + /* Finished with the need for root privileges. Drop to unprivileged user. */ + setreuid( userid, userid ); + setregid( groupid, groupid ); + } +#endif + + if(local_port > 0) + traceEvent(TRACE_NORMAL, "Binding to local port %d", local_port); + + if(edge_init_twofish( &eee, (u_int8_t *)(encrypt_key), strlen(encrypt_key) ) < 0) return(-1); + eee.sinfo.sock = open_socket(local_port, eee.sinfo.is_udp_socket, 0); + if(eee.sinfo.sock < 0) return(-1); + + if( !(eee.sinfo.is_udp_socket) ) { + int rc = connect_socket(eee.sinfo.sock, &(eee.supernode)); + + if(rc == -1) { + traceEvent(TRACE_WARNING, "Error while connecting to supernode\n"); + return(-1); + } + } + +#ifndef WIN32 + if ( fork_as_daemon ) + { + useSyslog=1; /* traceEvent output now goes to syslog. */ + daemon( 0, 0 ); + } +#endif + + update_registrations(&eee); + + traceEvent(TRACE_NORMAL, ""); + traceEvent(TRACE_NORMAL, "Ready"); + +#ifdef WIN32 + startTunReadThread(&eee); +#endif + + /* Main loop + * + * select() is used to wait for input on either the TAP fd or the UDP/TCP + * socket. When input is present the data is read and processed by either + * readFromIPSocket() or readFromTAPSocket() + */ + + while(1) { + int rc, max_sock = 0; + fd_set socket_mask; + struct timeval wait_time; + time_t nowTime; + + FD_ZERO(&socket_mask); + FD_SET(eee.sinfo.sock, &socket_mask); +#ifndef WIN32 + FD_SET(eee.device.fd, &socket_mask); + max_sock = max( eee.sinfo.sock, eee.device.fd ); +#endif + + wait_time.tv_sec = SOCKET_TIMEOUT_INTERVAL_SECS; wait_time.tv_usec = 0; + + rc = select(max_sock+1, &socket_mask, NULL, NULL, &wait_time); + nowTime=time(NULL); + + if(rc > 0) + { + /* Any or all of the FDs could have input; check them all. */ + + if(FD_ISSET(eee.sinfo.sock, &socket_mask)) + { + /* Read a cooked socket from the internet socket. Writes on the TAP + * socket. */ + readFromIPSocket(&eee); + } + +#ifndef WIN32 + if(FD_ISSET(eee.device.fd, &socket_mask)) + { + /* Read an ethernet frame from the TAP socket. Write on the IP + * socket. */ + readFromTAPSocket(&eee); + } +#endif + } + + update_registrations(&eee); + + numPurged = purge_expired_registrations( &(eee.known_peers) ); + numPurged += purge_expired_registrations( &(eee.pending_peers) ); + if ( numPurged > 0 ) + { + traceEvent( TRACE_NORMAL, "Peer removed: pending=%ld, operational=%ld", + peer_list_size( eee.pending_peers ), peer_list_size( eee.known_peers ) ); + } + + if ( ( nowTime - lastStatus ) > STATUS_UPDATE_INTERVAL ) + { + lastStatus = nowTime; + + traceEvent( TRACE_NORMAL, "STATUS: pending=%ld, operational=%ld", + peer_list_size( eee.pending_peers ), peer_list_size( eee.known_peers ) ); + } + } /* while */ + + send_deregister( &eee, &(eee.supernode)); + + closesocket(eee.sinfo.sock); + tuntap_close(&(eee.device)); + + edge_deinit( &eee ); + + return(0); +} + + diff --git a/lzoconf.h b/lzoconf.h new file mode 100644 index 0000000..cc437f1 --- /dev/null +++ b/lzoconf.h @@ -0,0 +1,417 @@ +/* lzoconf.h -- configuration for the LZO real-time data compression library + + This file is part of the LZO real-time data compression library. + + Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer + All Rights Reserved. + + The LZO library is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + The LZO 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with the LZO library; see the file COPYING. + If not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + Markus F.X.J. Oberhumer + + http://www.oberhumer.com/opensource/lzo/ + */ + + +#ifndef __LZOCONF_H_INCLUDED +#define __LZOCONF_H_INCLUDED + +#define LZO_VERSION 0x2030 +#define LZO_VERSION_STRING "2.03" +#define LZO_VERSION_DATE "Apr 30 2008" + +/* internal Autoconf configuration file - only used when building LZO */ +#if defined(LZO_HAVE_CONFIG_H) +# include +#endif +#include +#include + + +/*********************************************************************** +// LZO requires a conforming +************************************************************************/ + +#if !defined(CHAR_BIT) || (CHAR_BIT != 8) +# error "invalid CHAR_BIT" +#endif +#if !defined(UCHAR_MAX) || !defined(UINT_MAX) || !defined(ULONG_MAX) +# error "check your compiler installation" +#endif +#if (USHRT_MAX < 1) || (UINT_MAX < 1) || (ULONG_MAX < 1) +# error "your limits.h macros are broken" +#endif + +/* get OS and architecture defines */ +#ifndef __LZODEFS_H_INCLUDED +#include "lzodefs.h" +#endif + + +#ifdef __cplusplus +extern "C" { +#endif + + +/*********************************************************************** +// some core defines +************************************************************************/ + +#if !defined(LZO_UINT32_C) +# if (UINT_MAX < LZO_0xffffffffL) +# define LZO_UINT32_C(c) c ## UL +# else +# define LZO_UINT32_C(c) ((c) + 0U) +# endif +#endif + +/* memory checkers */ +#if !defined(__LZO_CHECKER) +# if defined(__BOUNDS_CHECKING_ON) +# define __LZO_CHECKER 1 +# elif defined(__CHECKER__) +# define __LZO_CHECKER 1 +# elif defined(__INSURE__) +# define __LZO_CHECKER 1 +# elif defined(__PURIFY__) +# define __LZO_CHECKER 1 +# endif +#endif + + +/*********************************************************************** +// integral and pointer types +************************************************************************/ + +/* lzo_uint should match size_t */ +#if !defined(LZO_UINT_MAX) +# if defined(LZO_ABI_LLP64) /* WIN64 */ +# if defined(LZO_OS_WIN64) + typedef unsigned __int64 lzo_uint; + typedef __int64 lzo_int; +# else + typedef unsigned long long lzo_uint; + typedef long long lzo_int; +# endif +# define LZO_UINT_MAX 0xffffffffffffffffull +# define LZO_INT_MAX 9223372036854775807LL +# define LZO_INT_MIN (-1LL - LZO_INT_MAX) +# elif defined(LZO_ABI_IP32L64) /* MIPS R5900 */ + typedef unsigned int lzo_uint; + typedef int lzo_int; +# define LZO_UINT_MAX UINT_MAX +# define LZO_INT_MAX INT_MAX +# define LZO_INT_MIN INT_MIN +# elif (ULONG_MAX >= LZO_0xffffffffL) + typedef unsigned long lzo_uint; + typedef long lzo_int; +# define LZO_UINT_MAX ULONG_MAX +# define LZO_INT_MAX LONG_MAX +# define LZO_INT_MIN LONG_MIN +# else +# error "lzo_uint" +# endif +#endif + +/* Integral types with 32 bits or more. */ +#if !defined(LZO_UINT32_MAX) +# if (UINT_MAX >= LZO_0xffffffffL) + typedef unsigned int lzo_uint32; + typedef int lzo_int32; +# define LZO_UINT32_MAX UINT_MAX +# define LZO_INT32_MAX INT_MAX +# define LZO_INT32_MIN INT_MIN +# elif (ULONG_MAX >= LZO_0xffffffffL) + typedef unsigned long lzo_uint32; + typedef long lzo_int32; +# define LZO_UINT32_MAX ULONG_MAX +# define LZO_INT32_MAX LONG_MAX +# define LZO_INT32_MIN LONG_MIN +# else +# error "lzo_uint32" +# endif +#endif + +/* The larger type of lzo_uint and lzo_uint32. */ +#if (LZO_UINT_MAX >= LZO_UINT32_MAX) +# define lzo_xint lzo_uint +#else +# define lzo_xint lzo_uint32 +#endif + +/* Memory model that allows to access memory at offsets of lzo_uint. */ +#if !defined(__LZO_MMODEL) +# if (LZO_UINT_MAX <= UINT_MAX) +# define __LZO_MMODEL +# elif defined(LZO_HAVE_MM_HUGE_PTR) +# define __LZO_MMODEL_HUGE 1 +# define __LZO_MMODEL __huge +# else +# define __LZO_MMODEL +# endif +#endif + +/* no typedef here because of const-pointer issues */ +#define lzo_bytep unsigned char __LZO_MMODEL * +#define lzo_charp char __LZO_MMODEL * +#define lzo_voidp void __LZO_MMODEL * +#define lzo_shortp short __LZO_MMODEL * +#define lzo_ushortp unsigned short __LZO_MMODEL * +#define lzo_uint32p lzo_uint32 __LZO_MMODEL * +#define lzo_int32p lzo_int32 __LZO_MMODEL * +#define lzo_uintp lzo_uint __LZO_MMODEL * +#define lzo_intp lzo_int __LZO_MMODEL * +#define lzo_xintp lzo_xint __LZO_MMODEL * +#define lzo_voidpp lzo_voidp __LZO_MMODEL * +#define lzo_bytepp lzo_bytep __LZO_MMODEL * +/* deprecated - use `lzo_bytep' instead of `lzo_byte *' */ +#define lzo_byte unsigned char __LZO_MMODEL + +typedef int lzo_bool; + + +/*********************************************************************** +// function types +************************************************************************/ + +/* name mangling */ +#if !defined(__LZO_EXTERN_C) +# ifdef __cplusplus +# define __LZO_EXTERN_C extern "C" +# else +# define __LZO_EXTERN_C extern +# endif +#endif + +/* calling convention */ +#if !defined(__LZO_CDECL) +# define __LZO_CDECL __lzo_cdecl +#endif + +/* DLL export information */ +#if !defined(__LZO_EXPORT1) +# define __LZO_EXPORT1 +#endif +#if !defined(__LZO_EXPORT2) +# define __LZO_EXPORT2 +#endif + +/* __cdecl calling convention for public C and assembly functions */ +#if !defined(LZO_PUBLIC) +# define LZO_PUBLIC(_rettype) __LZO_EXPORT1 _rettype __LZO_EXPORT2 __LZO_CDECL +#endif +#if !defined(LZO_EXTERN) +# define LZO_EXTERN(_rettype) __LZO_EXTERN_C LZO_PUBLIC(_rettype) +#endif +#if !defined(LZO_PRIVATE) +# define LZO_PRIVATE(_rettype) static _rettype __LZO_CDECL +#endif + +/* function types */ +typedef int +(__LZO_CDECL *lzo_compress_t) ( const lzo_bytep src, lzo_uint src_len, + lzo_bytep dst, lzo_uintp dst_len, + lzo_voidp wrkmem ); + +typedef int +(__LZO_CDECL *lzo_decompress_t) ( const lzo_bytep src, lzo_uint src_len, + lzo_bytep dst, lzo_uintp dst_len, + lzo_voidp wrkmem ); + +typedef int +(__LZO_CDECL *lzo_optimize_t) ( lzo_bytep src, lzo_uint src_len, + lzo_bytep dst, lzo_uintp dst_len, + lzo_voidp wrkmem ); + +typedef int +(__LZO_CDECL *lzo_compress_dict_t)(const lzo_bytep src, lzo_uint src_len, + lzo_bytep dst, lzo_uintp dst_len, + lzo_voidp wrkmem, + const lzo_bytep dict, lzo_uint dict_len ); + +typedef int +(__LZO_CDECL *lzo_decompress_dict_t)(const lzo_bytep src, lzo_uint src_len, + lzo_bytep dst, lzo_uintp dst_len, + lzo_voidp wrkmem, + const lzo_bytep dict, lzo_uint dict_len ); + + +/* Callback interface. Currently only the progress indicator ("nprogress") + * is used, but this may change in a future release. */ + +struct lzo_callback_t; +typedef struct lzo_callback_t lzo_callback_t; +#define lzo_callback_p lzo_callback_t __LZO_MMODEL * + +/* malloc & free function types */ +typedef lzo_voidp (__LZO_CDECL *lzo_alloc_func_t) + (lzo_callback_p self, lzo_uint items, lzo_uint size); +typedef void (__LZO_CDECL *lzo_free_func_t) + (lzo_callback_p self, lzo_voidp ptr); + +/* a progress indicator callback function */ +typedef void (__LZO_CDECL *lzo_progress_func_t) + (lzo_callback_p, lzo_uint, lzo_uint, int); + +struct lzo_callback_t +{ + /* custom allocators (set to 0 to disable) */ + lzo_alloc_func_t nalloc; /* [not used right now] */ + lzo_free_func_t nfree; /* [not used right now] */ + + /* a progress indicator callback function (set to 0 to disable) */ + lzo_progress_func_t nprogress; + + /* NOTE: the first parameter "self" of the nalloc/nfree/nprogress + * callbacks points back to this struct, so you are free to store + * some extra info in the following variables. */ + lzo_voidp user1; + lzo_xint user2; + lzo_xint user3; +}; + + +/*********************************************************************** +// error codes and prototypes +************************************************************************/ + +/* Error codes for the compression/decompression functions. Negative + * values are errors, positive values will be used for special but + * normal events. + */ +#define LZO_E_OK 0 +#define LZO_E_ERROR (-1) +#define LZO_E_OUT_OF_MEMORY (-2) /* [not used right now] */ +#define LZO_E_NOT_COMPRESSIBLE (-3) /* [not used right now] */ +#define LZO_E_INPUT_OVERRUN (-4) +#define LZO_E_OUTPUT_OVERRUN (-5) +#define LZO_E_LOOKBEHIND_OVERRUN (-6) +#define LZO_E_EOF_NOT_FOUND (-7) +#define LZO_E_INPUT_NOT_CONSUMED (-8) +#define LZO_E_NOT_YET_IMPLEMENTED (-9) /* [not used right now] */ + + +#ifndef lzo_sizeof_dict_t +# define lzo_sizeof_dict_t ((unsigned)sizeof(lzo_bytep)) +#endif + +/* lzo_init() should be the first function you call. + * Check the return code ! + * + * lzo_init() is a macro to allow checking that the library and the + * compiler's view of various types are consistent. + */ +#define lzo_init() __lzo_init_v2(LZO_VERSION,(int)sizeof(short),(int)sizeof(int),\ + (int)sizeof(long),(int)sizeof(lzo_uint32),(int)sizeof(lzo_uint),\ + (int)lzo_sizeof_dict_t,(int)sizeof(char *),(int)sizeof(lzo_voidp),\ + (int)sizeof(lzo_callback_t)) +LZO_EXTERN(int) __lzo_init_v2(unsigned,int,int,int,int,int,int,int,int,int); + +/* version functions (useful for shared libraries) */ +LZO_EXTERN(unsigned) lzo_version(void); +LZO_EXTERN(const char *) lzo_version_string(void); +LZO_EXTERN(const char *) lzo_version_date(void); +LZO_EXTERN(const lzo_charp) _lzo_version_string(void); +LZO_EXTERN(const lzo_charp) _lzo_version_date(void); + +/* string functions */ +LZO_EXTERN(int) +lzo_memcmp(const lzo_voidp _s1, const lzo_voidp _s2, lzo_uint _len); +LZO_EXTERN(lzo_voidp) +lzo_memcpy(lzo_voidp _dest, const lzo_voidp _src, lzo_uint _len); +LZO_EXTERN(lzo_voidp) +lzo_memmove(lzo_voidp _dest, const lzo_voidp _src, lzo_uint _len); +LZO_EXTERN(lzo_voidp) +lzo_memset(lzo_voidp _s, int _c, lzo_uint _len); + +/* checksum functions */ +LZO_EXTERN(lzo_uint32) +lzo_adler32(lzo_uint32 _adler, const lzo_bytep _buf, lzo_uint _len); +LZO_EXTERN(lzo_uint32) +lzo_crc32(lzo_uint32 _c, const lzo_bytep _buf, lzo_uint _len); +LZO_EXTERN(const lzo_uint32p) +lzo_get_crc32_table(void); + +/* misc. */ +LZO_EXTERN(int) _lzo_config_check(void); +typedef union { lzo_bytep p; lzo_uint u; } __lzo_pu_u; +typedef union { lzo_bytep p; lzo_uint32 u32; } __lzo_pu32_u; +typedef union { void *vp; lzo_bytep bp; lzo_uint32 u32; long l; } lzo_align_t; + +/* align a char pointer on a boundary that is a multiple of `size' */ +LZO_EXTERN(unsigned) __lzo_align_gap(const lzo_voidp _ptr, lzo_uint _size); +#define LZO_PTR_ALIGN_UP(_ptr,_size) \ + ((_ptr) + (lzo_uint) __lzo_align_gap((const lzo_voidp)(_ptr),(lzo_uint)(_size))) + + +/*********************************************************************** +// deprecated macros - only for backward compatibility with LZO v1.xx +************************************************************************/ + +#if defined(LZO_CFG_COMPAT) + +#define __LZOCONF_H 1 + +#if defined(LZO_ARCH_I086) +# define __LZO_i386 1 +#elif defined(LZO_ARCH_I386) +# define __LZO_i386 1 +#endif + +#if defined(LZO_OS_DOS16) +# define __LZO_DOS 1 +# define __LZO_DOS16 1 +#elif defined(LZO_OS_DOS32) +# define __LZO_DOS 1 +#elif defined(LZO_OS_WIN16) +# define __LZO_WIN 1 +# define __LZO_WIN16 1 +#elif defined(LZO_OS_WIN32) +# define __LZO_WIN 1 +#endif + +#define __LZO_CMODEL +#define __LZO_DMODEL +#define __LZO_ENTRY __LZO_CDECL +#define LZO_EXTERN_CDECL LZO_EXTERN +#define LZO_ALIGN LZO_PTR_ALIGN_UP + +#define lzo_compress_asm_t lzo_compress_t +#define lzo_decompress_asm_t lzo_decompress_t + +#endif /* LZO_CFG_COMPAT */ + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* already included */ + + +/* vim:set ts=4 et: */ diff --git a/lzodefs.h b/lzodefs.h new file mode 100644 index 0000000..1805637 --- /dev/null +++ b/lzodefs.h @@ -0,0 +1,1807 @@ +/* lzodefs.h -- architecture, OS and compiler specific defines + + This file is part of the LZO real-time data compression library. + + Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer + All Rights Reserved. + + The LZO library is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + The LZO 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with the LZO library; see the file COPYING. + If not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + Markus F.X.J. Oberhumer + + http://www.oberhumer.com/opensource/lzo/ + */ + + +#ifndef __LZODEFS_H_INCLUDED +#define __LZODEFS_H_INCLUDED 1 + +#if defined(__CYGWIN32__) && !defined(__CYGWIN__) +# define __CYGWIN__ __CYGWIN32__ +#endif +#if defined(__IBMCPP__) && !defined(__IBMC__) +# define __IBMC__ __IBMCPP__ +#endif +#if defined(__ICL) && defined(_WIN32) && !defined(__INTEL_COMPILER) +# define __INTEL_COMPILER __ICL +#endif +#if 1 && defined(__INTERIX) && defined(__GNUC__) && !defined(_ALL_SOURCE) +# define _ALL_SOURCE 1 +#endif +#if defined(__mips__) && defined(__R5900__) +# if !defined(__LONG_MAX__) +# define __LONG_MAX__ 9223372036854775807L +# endif +#endif +#if defined(__INTEL_COMPILER) && defined(__linux__) +# pragma warning(disable: 193) +#endif +#if defined(__KEIL__) && defined(__C166__) +# pragma warning disable = 322 +#elif 0 && defined(__C251__) +# pragma warning disable = 322 +#endif +#if defined(_MSC_VER) && !defined(__INTEL_COMPILER) && !defined(__MWERKS__) +# if (_MSC_VER >= 1300) +# pragma warning(disable: 4668) +# endif +#endif +#if 0 && defined(__WATCOMC__) +# if (__WATCOMC__ >= 1050) && (__WATCOMC__ < 1060) +# pragma warning 203 9 +# endif +#endif +#if defined(__BORLANDC__) && defined(__MSDOS__) && !defined(__FLAT__) +# pragma option -h +#endif +#if 0 +#define LZO_0xffffL 0xfffful +#define LZO_0xffffffffL 0xfffffffful +#else +#define LZO_0xffffL 65535ul +#define LZO_0xffffffffL 4294967295ul +#endif +#if (LZO_0xffffL == LZO_0xffffffffL) +# error "your preprocessor is broken 1" +#endif +#if (16ul * 16384ul != 262144ul) +# error "your preprocessor is broken 2" +#endif +#if 0 +#if (32767 >= 4294967295ul) +# error "your preprocessor is broken 3" +#endif +#if (65535u >= 4294967295ul) +# error "your preprocessor is broken 4" +#endif +#endif +#if (UINT_MAX == LZO_0xffffL) +#if defined(__ZTC__) && defined(__I86__) && !defined(__OS2__) +# if !defined(MSDOS) +# define MSDOS 1 +# endif +# if !defined(_MSDOS) +# define _MSDOS 1 +# endif +#elif 0 && defined(__VERSION) && defined(MB_LEN_MAX) +# if (__VERSION == 520) && (MB_LEN_MAX == 1) +# if !defined(__AZTEC_C__) +# define __AZTEC_C__ __VERSION +# endif +# if !defined(__DOS__) +# define __DOS__ 1 +# endif +# endif +#endif +#endif +#if defined(_MSC_VER) && defined(M_I86HM) && (UINT_MAX == LZO_0xffffL) +# define ptrdiff_t long +# define _PTRDIFF_T_DEFINED +#endif +#if (UINT_MAX == LZO_0xffffL) +# undef __LZO_RENAME_A +# undef __LZO_RENAME_B +# if defined(__AZTEC_C__) && defined(__DOS__) +# define __LZO_RENAME_A 1 +# elif defined(_MSC_VER) && defined(MSDOS) +# if (_MSC_VER < 600) +# define __LZO_RENAME_A 1 +# elif (_MSC_VER < 700) +# define __LZO_RENAME_B 1 +# endif +# elif defined(__TSC__) && defined(__OS2__) +# define __LZO_RENAME_A 1 +# elif defined(__MSDOS__) && defined(__TURBOC__) && (__TURBOC__ < 0x0410) +# define __LZO_RENAME_A 1 +# elif defined(__PACIFIC__) && defined(DOS) +# if !defined(__far) +# define __far far +# endif +# if !defined(__near) +# define __near near +# endif +# endif +# if defined(__LZO_RENAME_A) +# if !defined(__cdecl) +# define __cdecl cdecl +# endif +# if !defined(__far) +# define __far far +# endif +# if !defined(__huge) +# define __huge huge +# endif +# if !defined(__near) +# define __near near +# endif +# if !defined(__pascal) +# define __pascal pascal +# endif +# if !defined(__huge) +# define __huge huge +# endif +# elif defined(__LZO_RENAME_B) +# if !defined(__cdecl) +# define __cdecl _cdecl +# endif +# if !defined(__far) +# define __far _far +# endif +# if !defined(__huge) +# define __huge _huge +# endif +# if !defined(__near) +# define __near _near +# endif +# if !defined(__pascal) +# define __pascal _pascal +# endif +# elif (defined(__PUREC__) || defined(__TURBOC__)) && defined(__TOS__) +# if !defined(__cdecl) +# define __cdecl cdecl +# endif +# if !defined(__pascal) +# define __pascal pascal +# endif +# endif +# undef __LZO_RENAME_A +# undef __LZO_RENAME_B +#endif +#if (UINT_MAX == LZO_0xffffL) +#if defined(__AZTEC_C__) && defined(__DOS__) +# define LZO_BROKEN_CDECL_ALT_SYNTAX 1 +#elif defined(_MSC_VER) && defined(MSDOS) +# if (_MSC_VER < 600) +# define LZO_BROKEN_INTEGRAL_CONSTANTS 1 +# endif +# if (_MSC_VER < 700) +# define LZO_BROKEN_INTEGRAL_PROMOTION 1 +# define LZO_BROKEN_SIZEOF 1 +# endif +#elif defined(__PACIFIC__) && defined(DOS) +# define LZO_BROKEN_INTEGRAL_CONSTANTS 1 +#elif defined(__TURBOC__) && defined(__MSDOS__) +# if (__TURBOC__ < 0x0150) +# define LZO_BROKEN_CDECL_ALT_SYNTAX 1 +# define LZO_BROKEN_INTEGRAL_CONSTANTS 1 +# define LZO_BROKEN_INTEGRAL_PROMOTION 1 +# endif +# if (__TURBOC__ < 0x0200) +# define LZO_BROKEN_SIZEOF 1 +# endif +# if (__TURBOC__ < 0x0400) && defined(__cplusplus) +# define LZO_BROKEN_CDECL_ALT_SYNTAX 1 +# endif +#elif (defined(__PUREC__) || defined(__TURBOC__)) && defined(__TOS__) +# define LZO_BROKEN_CDECL_ALT_SYNTAX 1 +# define LZO_BROKEN_SIZEOF 1 +#endif +#endif +#if defined(__WATCOMC__) && (__WATCOMC__ < 900) +# define LZO_BROKEN_INTEGRAL_CONSTANTS 1 +#endif +#if defined(_CRAY) && defined(_CRAY1) +# define LZO_BROKEN_SIGNED_RIGHT_SHIFT 1 +#endif +#define LZO_PP_STRINGIZE(x) #x +#define LZO_PP_MACRO_EXPAND(x) LZO_PP_STRINGIZE(x) +#define LZO_PP_CONCAT2(a,b) a ## b +#define LZO_PP_CONCAT3(a,b,c) a ## b ## c +#define LZO_PP_CONCAT4(a,b,c,d) a ## b ## c ## d +#define LZO_PP_CONCAT5(a,b,c,d,e) a ## b ## c ## d ## e +#define LZO_PP_ECONCAT2(a,b) LZO_PP_CONCAT2(a,b) +#define LZO_PP_ECONCAT3(a,b,c) LZO_PP_CONCAT3(a,b,c) +#define LZO_PP_ECONCAT4(a,b,c,d) LZO_PP_CONCAT4(a,b,c,d) +#define LZO_PP_ECONCAT5(a,b,c,d,e) LZO_PP_CONCAT5(a,b,c,d,e) +#if 1 +#define LZO_CPP_STRINGIZE(x) #x +#define LZO_CPP_MACRO_EXPAND(x) LZO_CPP_STRINGIZE(x) +#define LZO_CPP_CONCAT2(a,b) a ## b +#define LZO_CPP_CONCAT3(a,b,c) a ## b ## c +#define LZO_CPP_CONCAT4(a,b,c,d) a ## b ## c ## d +#define LZO_CPP_CONCAT5(a,b,c,d,e) a ## b ## c ## d ## e +#define LZO_CPP_ECONCAT2(a,b) LZO_CPP_CONCAT2(a,b) +#define LZO_CPP_ECONCAT3(a,b,c) LZO_CPP_CONCAT3(a,b,c) +#define LZO_CPP_ECONCAT4(a,b,c,d) LZO_CPP_CONCAT4(a,b,c,d) +#define LZO_CPP_ECONCAT5(a,b,c,d,e) LZO_CPP_CONCAT5(a,b,c,d,e) +#endif +#define __LZO_MASK_GEN(o,b) (((((o) << ((b)-1)) - (o)) << 1) + (o)) +#if 1 && defined(__cplusplus) +# if !defined(__STDC_CONSTANT_MACROS) +# define __STDC_CONSTANT_MACROS 1 +# endif +# if !defined(__STDC_LIMIT_MACROS) +# define __STDC_LIMIT_MACROS 1 +# endif +#endif +#if defined(__cplusplus) +# define LZO_EXTERN_C extern "C" +#else +# define LZO_EXTERN_C extern +#endif +#if !defined(__LZO_OS_OVERRIDE) +#if defined(LZO_OS_FREESTANDING) +# define LZO_INFO_OS "freestanding" +#elif defined(LZO_OS_EMBEDDED) +# define LZO_INFO_OS "embedded" +#elif 1 && defined(__IAR_SYSTEMS_ICC__) +# define LZO_OS_EMBEDDED 1 +# define LZO_INFO_OS "embedded" +#elif defined(__CYGWIN__) && defined(__GNUC__) +# define LZO_OS_CYGWIN 1 +# define LZO_INFO_OS "cygwin" +#elif defined(__EMX__) && defined(__GNUC__) +# define LZO_OS_EMX 1 +# define LZO_INFO_OS "emx" +#elif defined(__BEOS__) +# define LZO_OS_BEOS 1 +# define LZO_INFO_OS "beos" +#elif defined(__Lynx__) +# define LZO_OS_LYNXOS 1 +# define LZO_INFO_OS "lynxos" +#elif defined(__OS400__) +# define LZO_OS_OS400 1 +# define LZO_INFO_OS "os400" +#elif defined(__QNX__) +# define LZO_OS_QNX 1 +# define LZO_INFO_OS "qnx" +#elif defined(__BORLANDC__) && defined(__DPMI32__) && (__BORLANDC__ >= 0x0460) +# define LZO_OS_DOS32 1 +# define LZO_INFO_OS "dos32" +#elif defined(__BORLANDC__) && defined(__DPMI16__) +# define LZO_OS_DOS16 1 +# define LZO_INFO_OS "dos16" +#elif defined(__ZTC__) && defined(DOS386) +# define LZO_OS_DOS32 1 +# define LZO_INFO_OS "dos32" +#elif defined(__OS2__) || defined(__OS2V2__) +# if (UINT_MAX == LZO_0xffffL) +# define LZO_OS_OS216 1 +# define LZO_INFO_OS "os216" +# elif (UINT_MAX == LZO_0xffffffffL) +# define LZO_OS_OS2 1 +# define LZO_INFO_OS "os2" +# else +# error "check your limits.h header" +# endif +#elif defined(__WIN64__) || defined(_WIN64) || defined(WIN64) +# define LZO_OS_WIN64 1 +# define LZO_INFO_OS "win64" +#elif defined(__WIN32__) || defined(_WIN32) || defined(WIN32) || defined(__WINDOWS_386__) +# define LZO_OS_WIN32 1 +# define LZO_INFO_OS "win32" +#elif defined(__MWERKS__) && defined(__INTEL__) +# define LZO_OS_WIN32 1 +# define LZO_INFO_OS "win32" +#elif defined(__WINDOWS__) || defined(_WINDOWS) || defined(_Windows) +# if (UINT_MAX == LZO_0xffffL) +# define LZO_OS_WIN16 1 +# define LZO_INFO_OS "win16" +# elif (UINT_MAX == LZO_0xffffffffL) +# define LZO_OS_WIN32 1 +# define LZO_INFO_OS "win32" +# else +# error "check your limits.h header" +# endif +#elif defined(__DOS__) || defined(__MSDOS__) || defined(_MSDOS) || defined(MSDOS) || (defined(__PACIFIC__) && defined(DOS)) +# if (UINT_MAX == LZO_0xffffL) +# define LZO_OS_DOS16 1 +# define LZO_INFO_OS "dos16" +# elif (UINT_MAX == LZO_0xffffffffL) +# define LZO_OS_DOS32 1 +# define LZO_INFO_OS "dos32" +# else +# error "check your limits.h header" +# endif +#elif defined(__WATCOMC__) +# if defined(__NT__) && (UINT_MAX == LZO_0xffffL) +# define LZO_OS_DOS16 1 +# define LZO_INFO_OS "dos16" +# elif defined(__NT__) && (__WATCOMC__ < 1100) +# define LZO_OS_WIN32 1 +# define LZO_INFO_OS "win32" +# elif defined(__linux__) || defined(__LINUX__) +# define LZO_OS_POSIX 1 +# define LZO_INFO_OS "posix" +# else +# error "please specify a target using the -bt compiler option" +# endif +#elif defined(__palmos__) +# define LZO_OS_PALMOS 1 +# define LZO_INFO_OS "palmos" +#elif defined(__TOS__) || defined(__atarist__) +# define LZO_OS_TOS 1 +# define LZO_INFO_OS "tos" +#elif defined(macintosh) && !defined(__ppc__) +# define LZO_OS_MACCLASSIC 1 +# define LZO_INFO_OS "macclassic" +#elif defined(__VMS) +# define LZO_OS_VMS 1 +# define LZO_INFO_OS "vms" +#elif ((defined(__mips__) && defined(__R5900__)) || defined(__MIPS_PSX2__)) +# define LZO_OS_CONSOLE 1 +# define LZO_OS_CONSOLE_PS2 1 +# define LZO_INFO_OS "console" +# define LZO_INFO_OS_CONSOLE "ps2" +#elif (defined(__mips__) && defined(__psp__)) +# define LZO_OS_CONSOLE 1 +# define LZO_OS_CONSOLE_PSP 1 +# define LZO_INFO_OS "console" +# define LZO_INFO_OS_CONSOLE "psp" +#else +# define LZO_OS_POSIX 1 +# define LZO_INFO_OS "posix" +#endif +#if (LZO_OS_POSIX) +# if defined(_AIX) || defined(__AIX__) || defined(__aix__) +# define LZO_OS_POSIX_AIX 1 +# define LZO_INFO_OS_POSIX "aix" +# elif defined(__FreeBSD__) +# define LZO_OS_POSIX_FREEBSD 1 +# define LZO_INFO_OS_POSIX "freebsd" +# elif defined(__hpux__) || defined(__hpux) +# define LZO_OS_POSIX_HPUX 1 +# define LZO_INFO_OS_POSIX "hpux" +# elif defined(__INTERIX) +# define LZO_OS_POSIX_INTERIX 1 +# define LZO_INFO_OS_POSIX "interix" +# elif defined(__IRIX__) || defined(__irix__) +# define LZO_OS_POSIX_IRIX 1 +# define LZO_INFO_OS_POSIX "irix" +# elif defined(__linux__) || defined(__linux) || defined(__LINUX__) +# define LZO_OS_POSIX_LINUX 1 +# define LZO_INFO_OS_POSIX "linux" +# elif defined(__APPLE__) || defined(__MACOS__) +# define LZO_OS_POSIX_MACOSX 1 +# define LZO_INFO_OS_POSIX "macosx" +# elif defined(__minix__) || defined(__minix) +# define LZO_OS_POSIX_MINIX 1 +# define LZO_INFO_OS_POSIX "minix" +# elif defined(__NetBSD__) +# define LZO_OS_POSIX_NETBSD 1 +# define LZO_INFO_OS_POSIX "netbsd" +# elif defined(__OpenBSD__) +# define LZO_OS_POSIX_OPENBSD 1 +# define LZO_INFO_OS_POSIX "openbsd" +# elif defined(__osf__) +# define LZO_OS_POSIX_OSF 1 +# define LZO_INFO_OS_POSIX "osf" +# elif defined(__solaris__) || defined(__sun) +# if defined(__SVR4) || defined(__svr4__) +# define LZO_OS_POSIX_SOLARIS 1 +# define LZO_INFO_OS_POSIX "solaris" +# else +# define LZO_OS_POSIX_SUNOS 1 +# define LZO_INFO_OS_POSIX "sunos" +# endif +# elif defined(__ultrix__) || defined(__ultrix) +# define LZO_OS_POSIX_ULTRIX 1 +# define LZO_INFO_OS_POSIX "ultrix" +# elif defined(_UNICOS) +# define LZO_OS_POSIX_UNICOS 1 +# define LZO_INFO_OS_POSIX "unicos" +# else +# define LZO_OS_POSIX_UNKNOWN 1 +# define LZO_INFO_OS_POSIX "unknown" +# endif +#endif +#endif +#if (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16) +# if (UINT_MAX != LZO_0xffffL) +# error "this should not happen" +# endif +# if (ULONG_MAX != LZO_0xffffffffL) +# error "this should not happen" +# endif +#endif +#if (LZO_OS_DOS32 || LZO_OS_OS2 || LZO_OS_WIN32 || LZO_OS_WIN64) +# if (UINT_MAX != LZO_0xffffffffL) +# error "this should not happen" +# endif +# if (ULONG_MAX != LZO_0xffffffffL) +# error "this should not happen" +# endif +#endif +#if defined(CIL) && defined(_GNUCC) && defined(__GNUC__) +# define LZO_CC_CILLY 1 +# define LZO_INFO_CC "Cilly" +# if defined(__CILLY__) +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__CILLY__) +# else +# define LZO_INFO_CCVER "unknown" +# endif +#elif 0 && defined(SDCC) && defined(__VERSION__) && !defined(__GNUC__) +# define LZO_CC_SDCC 1 +# define LZO_INFO_CC "sdcc" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(SDCC) +#elif defined(__PATHSCALE__) && defined(__PATHCC_PATCHLEVEL__) +# define LZO_CC_PATHSCALE (__PATHCC__ * 0x10000L + __PATHCC_MINOR__ * 0x100 + __PATHCC_PATCHLEVEL__) +# define LZO_INFO_CC "Pathscale C" +# define LZO_INFO_CCVER __PATHSCALE__ +#elif defined(__INTEL_COMPILER) +# define LZO_CC_INTELC 1 +# define LZO_INFO_CC "Intel C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__INTEL_COMPILER) +# if defined(_WIN32) || defined(_WIN64) +# define LZO_CC_SYNTAX_MSC 1 +# else +# define LZO_CC_SYNTAX_GNUC 1 +# endif +#elif defined(__POCC__) && defined(_WIN32) +# define LZO_CC_PELLESC 1 +# define LZO_INFO_CC "Pelles C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__POCC__) +#elif defined(__llvm__) && defined(__GNUC__) && defined(__VERSION__) +# if defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__) +# define LZO_CC_LLVM (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100 + __GNUC_PATCHLEVEL__) +# else +# define LZO_CC_LLVM (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100) +# endif +# define LZO_INFO_CC "llvm-gcc" +# define LZO_INFO_CCVER __VERSION__ +#elif defined(__GNUC__) && defined(__VERSION__) +# if defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__) +# define LZO_CC_GNUC (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100 + __GNUC_PATCHLEVEL__) +# elif defined(__GNUC_MINOR__) +# define LZO_CC_GNUC (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100) +# else +# define LZO_CC_GNUC (__GNUC__ * 0x10000L) +# endif +# define LZO_INFO_CC "gcc" +# define LZO_INFO_CCVER __VERSION__ +#elif defined(__ACK__) && defined(_ACK) +# define LZO_CC_ACK 1 +# define LZO_INFO_CC "Amsterdam Compiler Kit C" +# define LZO_INFO_CCVER "unknown" +#elif defined(__AZTEC_C__) +# define LZO_CC_AZTECC 1 +# define LZO_INFO_CC "Aztec C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__AZTEC_C__) +#elif defined(__BORLANDC__) +# define LZO_CC_BORLANDC 1 +# define LZO_INFO_CC "Borland C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__BORLANDC__) +#elif defined(_CRAYC) && defined(_RELEASE) +# define LZO_CC_CRAYC 1 +# define LZO_INFO_CC "Cray C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(_RELEASE) +#elif defined(__DMC__) && defined(__SC__) +# define LZO_CC_DMC 1 +# define LZO_INFO_CC "Digital Mars C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__DMC__) +#elif defined(__DECC) +# define LZO_CC_DECC 1 +# define LZO_INFO_CC "DEC C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__DECC) +#elif defined(__HIGHC__) +# define LZO_CC_HIGHC 1 +# define LZO_INFO_CC "MetaWare High C" +# define LZO_INFO_CCVER "unknown" +#elif defined(__IAR_SYSTEMS_ICC__) +# define LZO_CC_IARC 1 +# define LZO_INFO_CC "IAR C" +# if defined(__VER__) +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__VER__) +# else +# define LZO_INFO_CCVER "unknown" +# endif +#elif defined(__IBMC__) +# define LZO_CC_IBMC 1 +# define LZO_INFO_CC "IBM C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__IBMC__) +#elif defined(__KEIL__) && defined(__C166__) +# define LZO_CC_KEILC 1 +# define LZO_INFO_CC "Keil C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__C166__) +#elif defined(__LCC__) && defined(_WIN32) && defined(__LCCOPTIMLEVEL) +# define LZO_CC_LCCWIN32 1 +# define LZO_INFO_CC "lcc-win32" +# define LZO_INFO_CCVER "unknown" +#elif defined(__LCC__) +# define LZO_CC_LCC 1 +# define LZO_INFO_CC "lcc" +# if defined(__LCC_VERSION__) +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__LCC_VERSION__) +# else +# define LZO_INFO_CCVER "unknown" +# endif +#elif defined(_MSC_VER) +# define LZO_CC_MSC 1 +# define LZO_INFO_CC "Microsoft C" +# if defined(_MSC_FULL_VER) +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(_MSC_VER) "." LZO_PP_MACRO_EXPAND(_MSC_FULL_VER) +# else +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(_MSC_VER) +# endif +#elif defined(__MWERKS__) +# define LZO_CC_MWERKS 1 +# define LZO_INFO_CC "Metrowerks C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__MWERKS__) +#elif (defined(__NDPC__) || defined(__NDPX__)) && defined(__i386) +# define LZO_CC_NDPC 1 +# define LZO_INFO_CC "Microway NDP C" +# define LZO_INFO_CCVER "unknown" +#elif defined(__PACIFIC__) +# define LZO_CC_PACIFICC 1 +# define LZO_INFO_CC "Pacific C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__PACIFIC__) +#elif defined(__PGI) && (defined(__linux__) || defined(__WIN32__)) +# define LZO_CC_PGI 1 +# define LZO_INFO_CC "Portland Group PGI C" +# define LZO_INFO_CCVER "unknown" +#elif defined(__PUREC__) && defined(__TOS__) +# define LZO_CC_PUREC 1 +# define LZO_INFO_CC "Pure C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__PUREC__) +#elif defined(__SC__) && defined(__ZTC__) +# define LZO_CC_SYMANTECC 1 +# define LZO_INFO_CC "Symantec C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__SC__) +#elif defined(__SUNPRO_C) +# define LZO_INFO_CC "SunPro C" +# if ((__SUNPRO_C)+0 > 0) +# define LZO_CC_SUNPROC __SUNPRO_C +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__SUNPRO_C) +# else +# define LZO_CC_SUNPROC 1 +# define LZO_INFO_CCVER "unknown" +# endif +#elif defined(__SUNPRO_CC) +# define LZO_INFO_CC "SunPro C" +# if ((__SUNPRO_CC)+0 > 0) +# define LZO_CC_SUNPROC __SUNPRO_CC +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__SUNPRO_CC) +# else +# define LZO_CC_SUNPROC 1 +# define LZO_INFO_CCVER "unknown" +# endif +#elif defined(__TINYC__) +# define LZO_CC_TINYC 1 +# define LZO_INFO_CC "Tiny C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__TINYC__) +#elif defined(__TSC__) +# define LZO_CC_TOPSPEEDC 1 +# define LZO_INFO_CC "TopSpeed C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__TSC__) +#elif defined(__WATCOMC__) +# define LZO_CC_WATCOMC 1 +# define LZO_INFO_CC "Watcom C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__WATCOMC__) +#elif defined(__TURBOC__) +# define LZO_CC_TURBOC 1 +# define LZO_INFO_CC "Turbo C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__TURBOC__) +#elif defined(__ZTC__) +# define LZO_CC_ZORTECHC 1 +# define LZO_INFO_CC "Zortech C" +# if (__ZTC__ == 0x310) +# define LZO_INFO_CCVER "0x310" +# else +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__ZTC__) +# endif +#else +# define LZO_CC_UNKNOWN 1 +# define LZO_INFO_CC "unknown" +# define LZO_INFO_CCVER "unknown" +#endif +#if 0 && (LZO_CC_MSC && (_MSC_VER >= 1200)) && !defined(_MSC_FULL_VER) +# error "LZO_CC_MSC: _MSC_FULL_VER is not defined" +#endif +#if !defined(__LZO_ARCH_OVERRIDE) && !defined(LZO_ARCH_GENERIC) && defined(_CRAY) +# if (UINT_MAX > LZO_0xffffffffL) && defined(_CRAY) +# if defined(_CRAYMPP) || defined(_CRAYT3D) || defined(_CRAYT3E) +# define LZO_ARCH_CRAY_MPP 1 +# elif defined(_CRAY1) +# define LZO_ARCH_CRAY_PVP 1 +# endif +# endif +#endif +#if !defined(__LZO_ARCH_OVERRIDE) +#if defined(LZO_ARCH_GENERIC) +# define LZO_INFO_ARCH "generic" +#elif (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16) +# define LZO_ARCH_I086 1 +# define LZO_ARCH_IA16 1 +# define LZO_INFO_ARCH "i086" +#elif defined(__alpha__) || defined(__alpha) || defined(_M_ALPHA) +# define LZO_ARCH_ALPHA 1 +# define LZO_INFO_ARCH "alpha" +#elif (LZO_ARCH_CRAY_MPP) && (defined(_CRAYT3D) || defined(_CRAYT3E)) +# define LZO_ARCH_ALPHA 1 +# define LZO_INFO_ARCH "alpha" +#elif defined(__amd64__) || defined(__x86_64__) || defined(_M_AMD64) +# define LZO_ARCH_AMD64 1 +# define LZO_INFO_ARCH "amd64" +#elif defined(__thumb__) || (defined(_M_ARM) && defined(_M_THUMB)) +# define LZO_ARCH_ARM 1 +# define LZO_ARCH_ARM_THUMB 1 +# define LZO_INFO_ARCH "arm_thumb" +#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICCARM__) +# define LZO_ARCH_ARM 1 +# if defined(__CPU_MODE__) && ((__CPU_MODE__)+0 == 1) +# define LZO_ARCH_ARM_THUMB 1 +# define LZO_INFO_ARCH "arm_thumb" +# elif defined(__CPU_MODE__) && ((__CPU_MODE__)+0 == 2) +# define LZO_INFO_ARCH "arm" +# else +# define LZO_INFO_ARCH "arm" +# endif +#elif defined(__arm__) || defined(_M_ARM) +# define LZO_ARCH_ARM 1 +# define LZO_INFO_ARCH "arm" +#elif (UINT_MAX <= LZO_0xffffL) && defined(__AVR__) +# define LZO_ARCH_AVR 1 +# define LZO_INFO_ARCH "avr" +#elif defined(__bfin__) +# define LZO_ARCH_BLACKFIN 1 +# define LZO_INFO_ARCH "blackfin" +#elif (UINT_MAX == LZO_0xffffL) && defined(__C166__) +# define LZO_ARCH_C166 1 +# define LZO_INFO_ARCH "c166" +#elif defined(__cris__) +# define LZO_ARCH_CRIS 1 +# define LZO_INFO_ARCH "cris" +#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICCEZ80__) +# define LZO_ARCH_EZ80 1 +# define LZO_INFO_ARCH "ez80" +#elif defined(__H8300__) || defined(__H8300H__) || defined(__H8300S__) || defined(__H8300SX__) +# define LZO_ARCH_H8300 1 +# define LZO_INFO_ARCH "h8300" +#elif defined(__hppa__) || defined(__hppa) +# define LZO_ARCH_HPPA 1 +# define LZO_INFO_ARCH "hppa" +#elif defined(__386__) || defined(__i386__) || defined(__i386) || defined(_M_IX86) || defined(_M_I386) +# define LZO_ARCH_I386 1 +# define LZO_ARCH_IA32 1 +# define LZO_INFO_ARCH "i386" +#elif (LZO_CC_ZORTECHC && defined(__I86__)) +# define LZO_ARCH_I386 1 +# define LZO_ARCH_IA32 1 +# define LZO_INFO_ARCH "i386" +#elif (LZO_OS_DOS32 && LZO_CC_HIGHC) && defined(_I386) +# define LZO_ARCH_I386 1 +# define LZO_ARCH_IA32 1 +# define LZO_INFO_ARCH "i386" +#elif defined(__ia64__) || defined(__ia64) || defined(_M_IA64) +# define LZO_ARCH_IA64 1 +# define LZO_INFO_ARCH "ia64" +#elif (UINT_MAX == LZO_0xffffL) && defined(__m32c__) +# define LZO_ARCH_M16C 1 +# define LZO_INFO_ARCH "m16c" +#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICCM16C__) +# define LZO_ARCH_M16C 1 +# define LZO_INFO_ARCH "m16c" +#elif defined(__m32r__) +# define LZO_ARCH_M32R 1 +# define LZO_INFO_ARCH "m32r" +#elif (LZO_OS_TOS) || defined(__m68k__) || defined(__m68000__) || defined(__mc68000__) || defined(__mc68020__) || defined(_M_M68K) +# define LZO_ARCH_M68K 1 +# define LZO_INFO_ARCH "m68k" +#elif (UINT_MAX == LZO_0xffffL) && defined(__C251__) +# define LZO_ARCH_MCS251 1 +# define LZO_INFO_ARCH "mcs251" +#elif (UINT_MAX == LZO_0xffffL) && defined(__C51__) +# define LZO_ARCH_MCS51 1 +# define LZO_INFO_ARCH "mcs51" +#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICC8051__) +# define LZO_ARCH_MCS51 1 +# define LZO_INFO_ARCH "mcs51" +#elif defined(__mips__) || defined(__mips) || defined(_MIPS_ARCH) || defined(_M_MRX000) +# define LZO_ARCH_MIPS 1 +# define LZO_INFO_ARCH "mips" +#elif (UINT_MAX == LZO_0xffffL) && defined(__MSP430__) +# define LZO_ARCH_MSP430 1 +# define LZO_INFO_ARCH "msp430" +#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICC430__) +# define LZO_ARCH_MSP430 1 +# define LZO_INFO_ARCH "msp430" +#elif defined(__powerpc__) || defined(__powerpc) || defined(__ppc__) || defined(__PPC__) || defined(_M_PPC) || defined(_ARCH_PPC) || defined(_ARCH_PWR) +# define LZO_ARCH_POWERPC 1 +# define LZO_INFO_ARCH "powerpc" +#elif defined(__s390__) || defined(__s390) || defined(__s390x__) || defined(__s390x) +# define LZO_ARCH_S390 1 +# define LZO_INFO_ARCH "s390" +#elif defined(__sh__) || defined(_M_SH) +# define LZO_ARCH_SH 1 +# define LZO_INFO_ARCH "sh" +#elif defined(__sparc__) || defined(__sparc) || defined(__sparcv8) +# define LZO_ARCH_SPARC 1 +# define LZO_INFO_ARCH "sparc" +#elif defined(__SPU__) +# define LZO_ARCH_SPU 1 +# define LZO_INFO_ARCH "spu" +#elif (UINT_MAX == LZO_0xffffL) && defined(__z80) +# define LZO_ARCH_Z80 1 +# define LZO_INFO_ARCH "z80" +#elif (LZO_ARCH_CRAY_PVP) +# if defined(_CRAYSV1) +# define LZO_ARCH_CRAY_SV1 1 +# define LZO_INFO_ARCH "cray_sv1" +# elif (_ADDR64) +# define LZO_ARCH_CRAY_T90 1 +# define LZO_INFO_ARCH "cray_t90" +# elif (_ADDR32) +# define LZO_ARCH_CRAY_YMP 1 +# define LZO_INFO_ARCH "cray_ymp" +# else +# define LZO_ARCH_CRAY_XMP 1 +# define LZO_INFO_ARCH "cray_xmp" +# endif +#else +# define LZO_ARCH_UNKNOWN 1 +# define LZO_INFO_ARCH "unknown" +#endif +#endif +#if 1 && (LZO_ARCH_UNKNOWN) && (LZO_OS_DOS32 || LZO_OS_OS2) +# error "FIXME - missing define for CPU architecture" +#endif +#if 1 && (LZO_ARCH_UNKNOWN) && (LZO_OS_WIN32) +# error "FIXME - missing WIN32 define for CPU architecture" +#endif +#if 1 && (LZO_ARCH_UNKNOWN) && (LZO_OS_WIN64) +# error "FIXME - missing WIN64 define for CPU architecture" +#endif +#if (LZO_OS_OS216 || LZO_OS_WIN16) +# define LZO_ARCH_I086PM 1 +# define LZO_ARCH_IA16PM 1 +#elif 1 && (LZO_OS_DOS16 && defined(BLX286)) +# define LZO_ARCH_I086PM 1 +# define LZO_ARCH_IA16PM 1 +#elif 1 && (LZO_OS_DOS16 && defined(DOSX286)) +# define LZO_ARCH_I086PM 1 +# define LZO_ARCH_IA16PM 1 +#elif 1 && (LZO_OS_DOS16 && LZO_CC_BORLANDC && defined(__DPMI16__)) +# define LZO_ARCH_I086PM 1 +# define LZO_ARCH_IA16PM 1 +#endif +#if defined(LZO_ARCH_ARM_THUMB) && !defined(LZO_ARCH_ARM) +# error "this should not happen" +#endif +#if defined(LZO_ARCH_I086PM) && !defined(LZO_ARCH_I086) +# error "this should not happen" +#endif +#if (LZO_ARCH_I086) +# if (UINT_MAX != LZO_0xffffL) +# error "this should not happen" +# endif +# if (ULONG_MAX != LZO_0xffffffffL) +# error "this should not happen" +# endif +#endif +#if (LZO_ARCH_I386) +# if (UINT_MAX != LZO_0xffffL) && defined(__i386_int16__) +# error "this should not happen" +# endif +# if (UINT_MAX != LZO_0xffffffffL) && !defined(__i386_int16__) +# error "this should not happen" +# endif +# if (ULONG_MAX != LZO_0xffffffffL) +# error "this should not happen" +# endif +#endif +#if !defined(__LZO_MM_OVERRIDE) +#if (LZO_ARCH_I086) +#if (UINT_MAX != LZO_0xffffL) +# error "this should not happen" +#endif +#if defined(__TINY__) || defined(M_I86TM) || defined(_M_I86TM) +# define LZO_MM_TINY 1 +#elif defined(__HUGE__) || defined(_HUGE_) || defined(M_I86HM) || defined(_M_I86HM) +# define LZO_MM_HUGE 1 +#elif defined(__SMALL__) || defined(M_I86SM) || defined(_M_I86SM) || defined(SMALL_MODEL) +# define LZO_MM_SMALL 1 +#elif defined(__MEDIUM__) || defined(M_I86MM) || defined(_M_I86MM) +# define LZO_MM_MEDIUM 1 +#elif defined(__COMPACT__) || defined(M_I86CM) || defined(_M_I86CM) +# define LZO_MM_COMPACT 1 +#elif defined(__LARGE__) || defined(M_I86LM) || defined(_M_I86LM) || defined(LARGE_MODEL) +# define LZO_MM_LARGE 1 +#elif (LZO_CC_AZTECC) +# if defined(_LARGE_CODE) && defined(_LARGE_DATA) +# define LZO_MM_LARGE 1 +# elif defined(_LARGE_CODE) +# define LZO_MM_MEDIUM 1 +# elif defined(_LARGE_DATA) +# define LZO_MM_COMPACT 1 +# else +# define LZO_MM_SMALL 1 +# endif +#elif (LZO_CC_ZORTECHC && defined(__VCM__)) +# define LZO_MM_LARGE 1 +#else +# error "unknown memory model" +#endif +#if (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16) +#define LZO_HAVE_MM_HUGE_PTR 1 +#define LZO_HAVE_MM_HUGE_ARRAY 1 +#if (LZO_MM_TINY) +# undef LZO_HAVE_MM_HUGE_ARRAY +#endif +#if (LZO_CC_AZTECC || LZO_CC_PACIFICC || LZO_CC_ZORTECHC) +# undef LZO_HAVE_MM_HUGE_PTR +# undef LZO_HAVE_MM_HUGE_ARRAY +#elif (LZO_CC_DMC || LZO_CC_SYMANTECC) +# undef LZO_HAVE_MM_HUGE_ARRAY +#elif (LZO_CC_MSC && defined(_QC)) +# undef LZO_HAVE_MM_HUGE_ARRAY +# if (_MSC_VER < 600) +# undef LZO_HAVE_MM_HUGE_PTR +# endif +#elif (LZO_CC_TURBOC && (__TURBOC__ < 0x0295)) +# undef LZO_HAVE_MM_HUGE_ARRAY +#endif +#if (LZO_ARCH_I086PM) && !defined(LZO_HAVE_MM_HUGE_PTR) +# if (LZO_OS_DOS16) +# error "this should not happen" +# elif (LZO_CC_ZORTECHC) +# else +# error "this should not happen" +# endif +#endif +#ifdef __cplusplus +extern "C" { +#endif +#if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0200)) + extern void __near __cdecl _AHSHIFT(void); +# define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT) +#elif (LZO_CC_DMC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC) + extern void __near __cdecl _AHSHIFT(void); +# define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT) +#elif (LZO_CC_MSC || LZO_CC_TOPSPEEDC) + extern void __near __cdecl _AHSHIFT(void); +# define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT) +#elif (LZO_CC_TURBOC && (__TURBOC__ >= 0x0295)) + extern void __near __cdecl _AHSHIFT(void); +# define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT) +#elif ((LZO_CC_AZTECC || LZO_CC_PACIFICC || LZO_CC_TURBOC) && LZO_OS_DOS16) +# define LZO_MM_AHSHIFT 12 +#elif (LZO_CC_WATCOMC) + extern unsigned char _HShift; +# define LZO_MM_AHSHIFT ((unsigned) _HShift) +#else +# error "FIXME - implement LZO_MM_AHSHIFT" +#endif +#ifdef __cplusplus +} +#endif +#endif +#elif (LZO_ARCH_C166) +#if !defined(__MODEL__) +# error "FIXME - C166 __MODEL__" +#elif ((__MODEL__) == 0) +# define LZO_MM_SMALL 1 +#elif ((__MODEL__) == 1) +# define LZO_MM_SMALL 1 +#elif ((__MODEL__) == 2) +# define LZO_MM_LARGE 1 +#elif ((__MODEL__) == 3) +# define LZO_MM_TINY 1 +#elif ((__MODEL__) == 4) +# define LZO_MM_XTINY 1 +#elif ((__MODEL__) == 5) +# define LZO_MM_XSMALL 1 +#else +# error "FIXME - C166 __MODEL__" +#endif +#elif (LZO_ARCH_MCS251) +#if !defined(__MODEL__) +# error "FIXME - MCS251 __MODEL__" +#elif ((__MODEL__) == 0) +# define LZO_MM_SMALL 1 +#elif ((__MODEL__) == 2) +# define LZO_MM_LARGE 1 +#elif ((__MODEL__) == 3) +# define LZO_MM_TINY 1 +#elif ((__MODEL__) == 4) +# define LZO_MM_XTINY 1 +#elif ((__MODEL__) == 5) +# define LZO_MM_XSMALL 1 +#else +# error "FIXME - MCS251 __MODEL__" +#endif +#elif (LZO_ARCH_MCS51) +#if !defined(__MODEL__) +# error "FIXME - MCS51 __MODEL__" +#elif ((__MODEL__) == 1) +# define LZO_MM_SMALL 1 +#elif ((__MODEL__) == 2) +# define LZO_MM_LARGE 1 +#elif ((__MODEL__) == 3) +# define LZO_MM_TINY 1 +#elif ((__MODEL__) == 4) +# define LZO_MM_XTINY 1 +#elif ((__MODEL__) == 5) +# define LZO_MM_XSMALL 1 +#else +# error "FIXME - MCS51 __MODEL__" +#endif +#elif (LZO_ARCH_CRAY_PVP) +# define LZO_MM_PVP 1 +#else +# define LZO_MM_FLAT 1 +#endif +#if (LZO_MM_COMPACT) +# define LZO_INFO_MM "compact" +#elif (LZO_MM_FLAT) +# define LZO_INFO_MM "flat" +#elif (LZO_MM_HUGE) +# define LZO_INFO_MM "huge" +#elif (LZO_MM_LARGE) +# define LZO_INFO_MM "large" +#elif (LZO_MM_MEDIUM) +# define LZO_INFO_MM "medium" +#elif (LZO_MM_PVP) +# define LZO_INFO_MM "pvp" +#elif (LZO_MM_SMALL) +# define LZO_INFO_MM "small" +#elif (LZO_MM_TINY) +# define LZO_INFO_MM "tiny" +#else +# error "unknown memory model" +#endif +#endif +#if defined(SIZEOF_SHORT) +# define LZO_SIZEOF_SHORT (SIZEOF_SHORT) +#endif +#if defined(SIZEOF_INT) +# define LZO_SIZEOF_INT (SIZEOF_INT) +#endif +#if defined(SIZEOF_LONG) +# define LZO_SIZEOF_LONG (SIZEOF_LONG) +#endif +#if defined(SIZEOF_LONG_LONG) +# define LZO_SIZEOF_LONG_LONG (SIZEOF_LONG_LONG) +#endif +#if defined(SIZEOF___INT16) +# define LZO_SIZEOF___INT16 (SIZEOF___INT16) +#endif +#if defined(SIZEOF___INT32) +# define LZO_SIZEOF___INT32 (SIZEOF___INT32) +#endif +#if defined(SIZEOF___INT64) +# define LZO_SIZEOF___INT64 (SIZEOF___INT64) +#endif +#if defined(SIZEOF_VOID_P) +# define LZO_SIZEOF_VOID_P (SIZEOF_VOID_P) +#endif +#if defined(SIZEOF_SIZE_T) +# define LZO_SIZEOF_SIZE_T (SIZEOF_SIZE_T) +#endif +#if defined(SIZEOF_PTRDIFF_T) +# define LZO_SIZEOF_PTRDIFF_T (SIZEOF_PTRDIFF_T) +#endif +#define __LZO_LSR(x,b) (((x)+0ul) >> (b)) +#if !defined(LZO_SIZEOF_SHORT) +# if (LZO_ARCH_CRAY_PVP) +# define LZO_SIZEOF_SHORT 8 +# elif (USHRT_MAX == LZO_0xffffL) +# define LZO_SIZEOF_SHORT 2 +# elif (__LZO_LSR(USHRT_MAX,7) == 1) +# define LZO_SIZEOF_SHORT 1 +# elif (__LZO_LSR(USHRT_MAX,15) == 1) +# define LZO_SIZEOF_SHORT 2 +# elif (__LZO_LSR(USHRT_MAX,31) == 1) +# define LZO_SIZEOF_SHORT 4 +# elif (__LZO_LSR(USHRT_MAX,63) == 1) +# define LZO_SIZEOF_SHORT 8 +# elif (__LZO_LSR(USHRT_MAX,127) == 1) +# define LZO_SIZEOF_SHORT 16 +# else +# error "LZO_SIZEOF_SHORT" +# endif +#endif +#if !defined(LZO_SIZEOF_INT) +# if (LZO_ARCH_CRAY_PVP) +# define LZO_SIZEOF_INT 8 +# elif (UINT_MAX == LZO_0xffffL) +# define LZO_SIZEOF_INT 2 +# elif (UINT_MAX == LZO_0xffffffffL) +# define LZO_SIZEOF_INT 4 +# elif (__LZO_LSR(UINT_MAX,7) == 1) +# define LZO_SIZEOF_INT 1 +# elif (__LZO_LSR(UINT_MAX,15) == 1) +# define LZO_SIZEOF_INT 2 +# elif (__LZO_LSR(UINT_MAX,31) == 1) +# define LZO_SIZEOF_INT 4 +# elif (__LZO_LSR(UINT_MAX,63) == 1) +# define LZO_SIZEOF_INT 8 +# elif (__LZO_LSR(UINT_MAX,127) == 1) +# define LZO_SIZEOF_INT 16 +# else +# error "LZO_SIZEOF_INT" +# endif +#endif +#if !defined(LZO_SIZEOF_LONG) +# if (ULONG_MAX == LZO_0xffffffffL) +# define LZO_SIZEOF_LONG 4 +# elif (__LZO_LSR(ULONG_MAX,7) == 1) +# define LZO_SIZEOF_LONG 1 +# elif (__LZO_LSR(ULONG_MAX,15) == 1) +# define LZO_SIZEOF_LONG 2 +# elif (__LZO_LSR(ULONG_MAX,31) == 1) +# define LZO_SIZEOF_LONG 4 +# elif (__LZO_LSR(ULONG_MAX,63) == 1) +# define LZO_SIZEOF_LONG 8 +# elif (__LZO_LSR(ULONG_MAX,127) == 1) +# define LZO_SIZEOF_LONG 16 +# else +# error "LZO_SIZEOF_LONG" +# endif +#endif +#if !defined(LZO_SIZEOF_LONG_LONG) && !defined(LZO_SIZEOF___INT64) +#if (LZO_SIZEOF_LONG > 0 && LZO_SIZEOF_LONG < 8) +# if defined(__LONG_MAX__) && defined(__LONG_LONG_MAX__) +# if (LZO_CC_GNUC >= 0x030300ul) +# if ((__LONG_MAX__)+0 == (__LONG_LONG_MAX__)+0) +# define LZO_SIZEOF_LONG_LONG LZO_SIZEOF_LONG +# elif (__LZO_LSR(__LONG_LONG_MAX__,30) == 1) +# define LZO_SIZEOF_LONG_LONG 4 +# endif +# endif +# endif +#endif +#endif +#if !defined(LZO_SIZEOF_LONG_LONG) && !defined(LZO_SIZEOF___INT64) +#if (LZO_SIZEOF_LONG > 0 && LZO_SIZEOF_LONG < 8) +#if (LZO_ARCH_I086 && LZO_CC_DMC) +#elif (LZO_CC_CILLY) && defined(__GNUC__) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define LZO_SIZEOF_LONG_LONG 8 +#elif ((LZO_OS_WIN32 || LZO_OS_WIN64 || defined(_WIN32)) && LZO_CC_MSC && (_MSC_VER >= 1400)) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_OS_WIN64 || defined(_WIN64)) +# define LZO_SIZEOF___INT64 8 +#elif (LZO_ARCH_I386 && (LZO_CC_DMC)) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_ARCH_I386 && (LZO_CC_SYMANTECC && (__SC__ >= 0x700))) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_ARCH_I386 && (LZO_CC_INTELC && defined(__linux__))) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_ARCH_I386 && (LZO_CC_MWERKS || LZO_CC_PELLESC || LZO_CC_PGI || LZO_CC_SUNPROC)) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_ARCH_I386 && (LZO_CC_INTELC || LZO_CC_MSC)) +# define LZO_SIZEOF___INT64 8 +#elif ((LZO_OS_WIN32 || defined(_WIN32)) && (LZO_CC_MSC)) +# define LZO_SIZEOF___INT64 8 +#elif (LZO_ARCH_I386 && (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0520))) +# define LZO_SIZEOF___INT64 8 +#elif (LZO_ARCH_I386 && (LZO_CC_WATCOMC && (__WATCOMC__ >= 1100))) +# define LZO_SIZEOF___INT64 8 +#elif (LZO_CC_WATCOMC && defined(_INTEGRAL_MAX_BITS) && (_INTEGRAL_MAX_BITS == 64)) +# define LZO_SIZEOF___INT64 8 +#elif (LZO_OS_OS400 || defined(__OS400__)) && defined(__LLP64_IFC__) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (defined(__vms) || defined(__VMS)) && (__INITIAL_POINTER_SIZE+0 == 64) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_CC_SDCC) && (LZO_SIZEOF_INT == 2) +#elif 1 && defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) +# define LZO_SIZEOF_LONG_LONG 8 +#endif +#endif +#endif +#if defined(__cplusplus) && defined(LZO_CC_GNUC) +# if (LZO_CC_GNUC < 0x020800ul) +# undef LZO_SIZEOF_LONG_LONG +# endif +#endif +#if defined(LZO_CFG_NO_LONG_LONG) || defined(__NO_LONG_LONG) +# undef LZO_SIZEOF_LONG_LONG +#endif +#if !defined(LZO_SIZEOF_VOID_P) +#if (LZO_ARCH_I086) +# define __LZO_WORDSIZE 2 +# if (LZO_MM_TINY || LZO_MM_SMALL || LZO_MM_MEDIUM) +# define LZO_SIZEOF_VOID_P 2 +# elif (LZO_MM_COMPACT || LZO_MM_LARGE || LZO_MM_HUGE) +# define LZO_SIZEOF_VOID_P 4 +# else +# error "LZO_MM" +# endif +#elif (LZO_ARCH_AVR || LZO_ARCH_Z80) +# define __LZO_WORDSIZE 1 +# define LZO_SIZEOF_VOID_P 2 +#elif (LZO_ARCH_C166 || LZO_ARCH_MCS51 || LZO_ARCH_MCS251 || LZO_ARCH_MSP430) +# define LZO_SIZEOF_VOID_P 2 +#elif (LZO_ARCH_H8300) +# if defined(__NORMAL_MODE__) +# define __LZO_WORDSIZE 4 +# define LZO_SIZEOF_VOID_P 2 +# elif defined(__H8300H__) || defined(__H8300S__) || defined(__H8300SX__) +# define __LZO_WORDSIZE 4 +# define LZO_SIZEOF_VOID_P 4 +# else +# define __LZO_WORDSIZE 2 +# define LZO_SIZEOF_VOID_P 2 +# endif +# if (LZO_CC_GNUC && (LZO_CC_GNUC < 0x040000ul)) && (LZO_SIZEOF_INT == 4) +# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_INT +# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_INT +# endif +#elif (LZO_ARCH_M16C) +# define __LZO_WORDSIZE 2 +# if defined(__m32c_cpu__) || defined(__m32cm_cpu__) +# define LZO_SIZEOF_VOID_P 4 +# else +# define LZO_SIZEOF_VOID_P 2 +# endif +#elif (LZO_SIZEOF_LONG == 8) && ((defined(__mips__) && defined(__R5900__)) || defined(__MIPS_PSX2__)) +# define __LZO_WORDSIZE 8 +# define LZO_SIZEOF_VOID_P 4 +#elif defined(__LLP64__) || defined(__LLP64) || defined(_LLP64) || defined(_WIN64) +# define __LZO_WORDSIZE 8 +# define LZO_SIZEOF_VOID_P 8 +#elif (LZO_OS_OS400 || defined(__OS400__)) && defined(__LLP64_IFC__) +# define LZO_SIZEOF_VOID_P LZO_SIZEOF_LONG +# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_LONG +# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_LONG +#elif (LZO_OS_OS400 || defined(__OS400__)) +# define __LZO_WORDSIZE LZO_SIZEOF_LONG +# define LZO_SIZEOF_VOID_P 16 +# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_LONG +# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_LONG +#elif (defined(__vms) || defined(__VMS)) && (__INITIAL_POINTER_SIZE+0 == 64) +# define LZO_SIZEOF_VOID_P 8 +# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_LONG +# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_LONG +#elif (LZO_ARCH_SPU) +# if 0 +# define __LZO_WORDSIZE 16 +# endif +# define LZO_SIZEOF_VOID_P 4 +#else +# define LZO_SIZEOF_VOID_P LZO_SIZEOF_LONG +#endif +#endif +#if !defined(LZO_WORDSIZE) +# if defined(__LZO_WORDSIZE) +# define LZO_WORDSIZE __LZO_WORDSIZE +# else +# define LZO_WORDSIZE LZO_SIZEOF_VOID_P +# endif +#endif +#if !defined(LZO_SIZEOF_SIZE_T) +#if (LZO_ARCH_I086 || LZO_ARCH_M16C) +# define LZO_SIZEOF_SIZE_T 2 +#else +# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_VOID_P +#endif +#endif +#if !defined(LZO_SIZEOF_PTRDIFF_T) +#if (LZO_ARCH_I086) +# if (LZO_MM_TINY || LZO_MM_SMALL || LZO_MM_MEDIUM || LZO_MM_HUGE) +# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_VOID_P +# elif (LZO_MM_COMPACT || LZO_MM_LARGE) +# if (LZO_CC_BORLANDC || LZO_CC_TURBOC) +# define LZO_SIZEOF_PTRDIFF_T 4 +# else +# define LZO_SIZEOF_PTRDIFF_T 2 +# endif +# else +# error "LZO_MM" +# endif +#else +# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_SIZE_T +#endif +#endif +#if defined(LZO_ABI_NEUTRAL_ENDIAN) +# undef LZO_ABI_BIG_ENDIAN +# undef LZO_ABI_LITTLE_ENDIAN +#elif !defined(LZO_ABI_BIG_ENDIAN) && !defined(LZO_ABI_LITTLE_ENDIAN) +#if (LZO_ARCH_ALPHA) && (LZO_ARCH_CRAY_MPP) +# define LZO_ABI_BIG_ENDIAN 1 +#elif (LZO_ARCH_ALPHA || LZO_ARCH_AMD64 || LZO_ARCH_BLACKFIN || LZO_ARCH_CRIS || LZO_ARCH_I086 || LZO_ARCH_I386 || LZO_ARCH_MSP430) +# define LZO_ABI_LITTLE_ENDIAN 1 +#elif (LZO_ARCH_M68K || LZO_ARCH_S390) +# define LZO_ABI_BIG_ENDIAN 1 +#elif 1 && defined(__IAR_SYSTEMS_ICC__) && defined(__LITTLE_ENDIAN__) +# if (__LITTLE_ENDIAN__ == 1) +# define LZO_ABI_LITTLE_ENDIAN 1 +# else +# define LZO_ABI_BIG_ENDIAN 1 +# endif +#elif 1 && defined(__BIG_ENDIAN__) && !defined(__LITTLE_ENDIAN__) +# define LZO_ABI_BIG_ENDIAN 1 +#elif 1 && defined(__LITTLE_ENDIAN__) && !defined(__BIG_ENDIAN__) +# define LZO_ABI_LITTLE_ENDIAN 1 +#elif 1 && (LZO_ARCH_ARM) && defined(__ARMEB__) && !defined(__ARMEL__) +# define LZO_ABI_BIG_ENDIAN 1 +#elif 1 && (LZO_ARCH_ARM) && defined(__ARMEL__) && !defined(__ARMEB__) +# define LZO_ABI_LITTLE_ENDIAN 1 +#elif 1 && (LZO_ARCH_MIPS) && defined(__MIPSEB__) && !defined(__MIPSEL__) +# define LZO_ABI_BIG_ENDIAN 1 +#elif 1 && (LZO_ARCH_MIPS) && defined(__MIPSEL__) && !defined(__MIPSEB__) +# define LZO_ABI_LITTLE_ENDIAN 1 +#endif +#endif +#if defined(LZO_ABI_BIG_ENDIAN) && defined(LZO_ABI_LITTLE_ENDIAN) +# error "this should not happen" +#endif +#if defined(LZO_ABI_BIG_ENDIAN) +# define LZO_INFO_ABI_ENDIAN "be" +#elif defined(LZO_ABI_LITTLE_ENDIAN) +# define LZO_INFO_ABI_ENDIAN "le" +#elif defined(LZO_ABI_NEUTRAL_ENDIAN) +# define LZO_INFO_ABI_ENDIAN "neutral" +#endif +#if (LZO_SIZEOF_INT == 1 && LZO_SIZEOF_LONG == 2 && LZO_SIZEOF_VOID_P == 2) +# define LZO_ABI_I8LP16 1 +# define LZO_INFO_ABI_PM "i8lp16" +#elif (LZO_SIZEOF_INT == 2 && LZO_SIZEOF_LONG == 2 && LZO_SIZEOF_VOID_P == 2) +# define LZO_ABI_ILP16 1 +# define LZO_INFO_ABI_PM "ilp16" +#elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 4 && LZO_SIZEOF_VOID_P == 4) +# define LZO_ABI_ILP32 1 +# define LZO_INFO_ABI_PM "ilp32" +#elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 4 && LZO_SIZEOF_VOID_P == 8 && LZO_SIZEOF_SIZE_T == 8) +# define LZO_ABI_LLP64 1 +# define LZO_INFO_ABI_PM "llp64" +#elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 8 && LZO_SIZEOF_VOID_P == 8) +# define LZO_ABI_LP64 1 +# define LZO_INFO_ABI_PM "lp64" +#elif (LZO_SIZEOF_INT == 8 && LZO_SIZEOF_LONG == 8 && LZO_SIZEOF_VOID_P == 8) +# define LZO_ABI_ILP64 1 +# define LZO_INFO_ABI_PM "ilp64" +#elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 8 && LZO_SIZEOF_VOID_P == 4) +# define LZO_ABI_IP32L64 1 +# define LZO_INFO_ABI_PM "ip32l64" +#endif +#if !defined(__LZO_LIBC_OVERRIDE) +#if defined(LZO_LIBC_NAKED) +# define LZO_INFO_LIBC "naked" +#elif defined(LZO_LIBC_FREESTANDING) +# define LZO_INFO_LIBC "freestanding" +#elif defined(LZO_LIBC_MOSTLY_FREESTANDING) +# define LZO_INFO_LIBC "mfreestanding" +#elif defined(LZO_LIBC_ISOC90) +# define LZO_INFO_LIBC "isoc90" +#elif defined(LZO_LIBC_ISOC99) +# define LZO_INFO_LIBC "isoc99" +#elif defined(__dietlibc__) +# define LZO_LIBC_DIETLIBC 1 +# define LZO_INFO_LIBC "dietlibc" +#elif defined(_NEWLIB_VERSION) +# define LZO_LIBC_NEWLIB 1 +# define LZO_INFO_LIBC "newlib" +#elif defined(__UCLIBC__) && defined(__UCLIBC_MAJOR__) && defined(__UCLIBC_MINOR__) +# if defined(__UCLIBC_SUBLEVEL__) +# define LZO_LIBC_UCLIBC (__UCLIBC_MAJOR__ * 0x10000L + __UCLIBC_MINOR__ * 0x100 + __UCLIBC_SUBLEVEL__) +# else +# define LZO_LIBC_UCLIBC 0x00090bL +# endif +# define LZO_INFO_LIBC "uclibc" +#elif defined(__GLIBC__) && defined(__GLIBC_MINOR__) +# define LZO_LIBC_GLIBC (__GLIBC__ * 0x10000L + __GLIBC_MINOR__ * 0x100) +# define LZO_INFO_LIBC "glibc" +#elif (LZO_CC_MWERKS) && defined(__MSL__) +# define LZO_LIBC_MSL __MSL__ +# define LZO_INFO_LIBC "msl" +#elif 1 && defined(__IAR_SYSTEMS_ICC__) +# define LZO_LIBC_ISOC90 1 +# define LZO_INFO_LIBC "isoc90" +#else +# define LZO_LIBC_DEFAULT 1 +# define LZO_INFO_LIBC "default" +#endif +#endif +#if !defined(__lzo_gnuc_extension__) +#if (LZO_CC_GNUC >= 0x020800ul) +# define __lzo_gnuc_extension__ __extension__ +#elif (LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_gnuc_extension__ __extension__ +#else +# define __lzo_gnuc_extension__ +#endif +#endif +#if !defined(__lzo_ua_volatile) +# define __lzo_ua_volatile volatile +#endif +#if !defined(__lzo_alignof) +#if (LZO_CC_CILLY || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI) +# define __lzo_alignof(e) __alignof__(e) +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 700)) +# define __lzo_alignof(e) __alignof__(e) +#elif (LZO_CC_MSC && (_MSC_VER >= 1300)) +# define __lzo_alignof(e) __alignof(e) +#endif +#endif +#if defined(__lzo_alignof) +# define __lzo_HAVE_alignof 1 +#endif +#if !defined(__lzo_constructor) +#if (LZO_CC_GNUC >= 0x030400ul) +# define __lzo_constructor __attribute__((__constructor__,__used__)) +#elif (LZO_CC_GNUC >= 0x020700ul) +# define __lzo_constructor __attribute__((__constructor__)) +#elif (LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_constructor __attribute__((__constructor__)) +#endif +#endif +#if defined(__lzo_constructor) +# define __lzo_HAVE_constructor 1 +#endif +#if !defined(__lzo_destructor) +#if (LZO_CC_GNUC >= 0x030400ul) +# define __lzo_destructor __attribute__((__destructor__,__used__)) +#elif (LZO_CC_GNUC >= 0x020700ul) +# define __lzo_destructor __attribute__((__destructor__)) +#elif (LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_destructor __attribute__((__destructor__)) +#endif +#endif +#if defined(__lzo_destructor) +# define __lzo_HAVE_destructor 1 +#endif +#if defined(__lzo_HAVE_destructor) && !defined(__lzo_HAVE_constructor) +# error "this should not happen" +#endif +#if !defined(__lzo_inline) +#if (LZO_CC_TURBOC && (__TURBOC__ <= 0x0295)) +#elif defined(__cplusplus) +# define __lzo_inline inline +#elif (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0550)) +# define __lzo_inline __inline +#elif (LZO_CC_CILLY || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI) +# define __lzo_inline __inline__ +#elif (LZO_CC_DMC) +# define __lzo_inline __inline +#elif (LZO_CC_INTELC) +# define __lzo_inline __inline +#elif (LZO_CC_MWERKS && (__MWERKS__ >= 0x2405)) +# define __lzo_inline __inline +#elif (LZO_CC_MSC && (_MSC_VER >= 900)) +# define __lzo_inline __inline +#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) +# define __lzo_inline inline +#endif +#endif +#if defined(__lzo_inline) +# define __lzo_HAVE_inline 1 +#else +# define __lzo_inline +#endif +#if !defined(__lzo_forceinline) +#if (LZO_CC_GNUC >= 0x030200ul) +# define __lzo_forceinline __inline__ __attribute__((__always_inline__)) +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 450) && LZO_CC_SYNTAX_MSC) +# define __lzo_forceinline __forceinline +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 800) && LZO_CC_SYNTAX_GNUC) +# define __lzo_forceinline __inline__ __attribute__((__always_inline__)) +#elif (LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_forceinline __inline__ __attribute__((__always_inline__)) +#elif (LZO_CC_MSC && (_MSC_VER >= 1200)) +# define __lzo_forceinline __forceinline +#endif +#endif +#if defined(__lzo_forceinline) +# define __lzo_HAVE_forceinline 1 +#else +# define __lzo_forceinline +#endif +#if !defined(__lzo_noinline) +#if 1 && (LZO_ARCH_I386) && (LZO_CC_GNUC >= 0x040000ul) && (LZO_CC_GNUC < 0x040003ul) +# define __lzo_noinline __attribute__((__noinline__,__used__)) +#elif (LZO_CC_GNUC >= 0x030200ul) +# define __lzo_noinline __attribute__((__noinline__)) +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 600) && LZO_CC_SYNTAX_MSC) +# define __lzo_noinline __declspec(noinline) +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 800) && LZO_CC_SYNTAX_GNUC) +# define __lzo_noinline __attribute__((__noinline__)) +#elif (LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_noinline __attribute__((__noinline__)) +#elif (LZO_CC_MSC && (_MSC_VER >= 1300)) +# define __lzo_noinline __declspec(noinline) +#elif (LZO_CC_MWERKS && (__MWERKS__ >= 0x3200) && (LZO_OS_WIN32 || LZO_OS_WIN64)) +# if defined(__cplusplus) +# else +# define __lzo_noinline __declspec(noinline) +# endif +#endif +#endif +#if defined(__lzo_noinline) +# define __lzo_HAVE_noinline 1 +#else +# define __lzo_noinline +#endif +#if (defined(__lzo_HAVE_forceinline) || defined(__lzo_HAVE_noinline)) && !defined(__lzo_HAVE_inline) +# error "this should not happen" +#endif +#if !defined(__lzo_noreturn) +#if (LZO_CC_GNUC >= 0x020700ul) +# define __lzo_noreturn __attribute__((__noreturn__)) +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 450) && LZO_CC_SYNTAX_MSC) +# define __lzo_noreturn __declspec(noreturn) +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 600) && LZO_CC_SYNTAX_GNUC) +# define __lzo_noreturn __attribute__((__noreturn__)) +#elif (LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_noreturn __attribute__((__noreturn__)) +#elif (LZO_CC_MSC && (_MSC_VER >= 1200)) +# define __lzo_noreturn __declspec(noreturn) +#endif +#endif +#if defined(__lzo_noreturn) +# define __lzo_HAVE_noreturn 1 +#else +# define __lzo_noreturn +#endif +#if !defined(__lzo_nothrow) +#if (LZO_CC_GNUC >= 0x030300ul) +# define __lzo_nothrow __attribute__((__nothrow__)) +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 450) && LZO_CC_SYNTAX_MSC) && defined(__cplusplus) +# define __lzo_nothrow __declspec(nothrow) +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 800) && LZO_CC_SYNTAX_GNUC) +# define __lzo_nothrow __attribute__((__nothrow__)) +#elif (LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_nothrow __attribute__((__nothrow__)) +#elif (LZO_CC_MSC && (_MSC_VER >= 1200)) && defined(__cplusplus) +# define __lzo_nothrow __declspec(nothrow) +#endif +#endif +#if defined(__lzo_nothrow) +# define __lzo_HAVE_nothrow 1 +#else +# define __lzo_nothrow +#endif +#if !defined(__lzo_restrict) +#if (LZO_CC_GNUC >= 0x030400ul) +# define __lzo_restrict __restrict__ +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 600) && LZO_CC_SYNTAX_GNUC) +# define __lzo_restrict __restrict__ +#elif (LZO_CC_LLVM) +# define __lzo_restrict __restrict__ +#elif (LZO_CC_MSC && (_MSC_VER >= 1400)) +# define __lzo_restrict __restrict +#endif +#endif +#if defined(__lzo_restrict) +# define __lzo_HAVE_restrict 1 +#else +# define __lzo_restrict +#endif +#if !defined(__lzo_likely) && !defined(__lzo_unlikely) +#if (LZO_CC_GNUC >= 0x030200ul) +# define __lzo_likely(e) (__builtin_expect(!!(e),1)) +# define __lzo_unlikely(e) (__builtin_expect(!!(e),0)) +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 800)) +# define __lzo_likely(e) (__builtin_expect(!!(e),1)) +# define __lzo_unlikely(e) (__builtin_expect(!!(e),0)) +#elif (LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_likely(e) (__builtin_expect(!!(e),1)) +# define __lzo_unlikely(e) (__builtin_expect(!!(e),0)) +#endif +#endif +#if defined(__lzo_likely) +# define __lzo_HAVE_likely 1 +#else +# define __lzo_likely(e) (e) +#endif +#if defined(__lzo_unlikely) +# define __lzo_HAVE_unlikely 1 +#else +# define __lzo_unlikely(e) (e) +#endif +#if !defined(LZO_UNUSED) +# if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0600)) +# define LZO_UNUSED(var) ((void) &var) +# elif (LZO_CC_BORLANDC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PELLESC || LZO_CC_TURBOC) +# define LZO_UNUSED(var) if (&var) ; else +# elif (LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define LZO_UNUSED(var) ((void) var) +# elif (LZO_CC_MSC && (_MSC_VER < 900)) +# define LZO_UNUSED(var) if (&var) ; else +# elif (LZO_CC_KEILC) +# define LZO_UNUSED(var) {extern int __lzo_unused[1-2*!(sizeof(var)>0)];} +# elif (LZO_CC_PACIFICC) +# define LZO_UNUSED(var) ((void) sizeof(var)) +# elif (LZO_CC_WATCOMC) && defined(__cplusplus) +# define LZO_UNUSED(var) ((void) var) +# else +# define LZO_UNUSED(var) ((void) &var) +# endif +#endif +#if !defined(LZO_UNUSED_FUNC) +# if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0600)) +# define LZO_UNUSED_FUNC(func) ((void) func) +# elif (LZO_CC_BORLANDC || LZO_CC_NDPC || LZO_CC_TURBOC) +# define LZO_UNUSED_FUNC(func) if (func) ; else +# elif (LZO_CC_LLVM) +# define LZO_UNUSED_FUNC(func) ((void) &func) +# elif (LZO_CC_MSC && (_MSC_VER < 900)) +# define LZO_UNUSED_FUNC(func) if (func) ; else +# elif (LZO_CC_MSC) +# define LZO_UNUSED_FUNC(func) ((void) &func) +# elif (LZO_CC_KEILC || LZO_CC_PELLESC) +# define LZO_UNUSED_FUNC(func) {extern int __lzo_unused[1-2*!(sizeof((int)func)>0)];} +# else +# define LZO_UNUSED_FUNC(func) ((void) func) +# endif +#endif +#if !defined(LZO_UNUSED_LABEL) +# if (LZO_CC_WATCOMC) && defined(__cplusplus) +# define LZO_UNUSED_LABEL(l) switch(0) case 1:goto l +# elif (LZO_CC_INTELC || LZO_CC_WATCOMC) +# define LZO_UNUSED_LABEL(l) if (0) goto l +# else +# define LZO_UNUSED_LABEL(l) switch(0) case 1:goto l +# endif +#endif +#if !defined(LZO_DEFINE_UNINITIALIZED_VAR) +# if 0 +# define LZO_DEFINE_UNINITIALIZED_VAR(type,var,init) type var +# elif 0 && (LZO_CC_GNUC) +# define LZO_DEFINE_UNINITIALIZED_VAR(type,var,init) type var = var +# else +# define LZO_DEFINE_UNINITIALIZED_VAR(type,var,init) type var = init +# endif +#endif +#if !defined(LZO_COMPILE_TIME_ASSERT_HEADER) +# if (LZO_CC_AZTECC || LZO_CC_ZORTECHC) +# define LZO_COMPILE_TIME_ASSERT_HEADER(e) extern int __lzo_cta[1-!(e)]; +# elif (LZO_CC_DMC || LZO_CC_SYMANTECC) +# define LZO_COMPILE_TIME_ASSERT_HEADER(e) extern int __lzo_cta[1u-2*!(e)]; +# elif (LZO_CC_TURBOC && (__TURBOC__ == 0x0295)) +# define LZO_COMPILE_TIME_ASSERT_HEADER(e) extern int __lzo_cta[1-!(e)]; +# else +# define LZO_COMPILE_TIME_ASSERT_HEADER(e) extern int __lzo_cta[1-2*!(e)]; +# endif +#endif +#if !defined(LZO_COMPILE_TIME_ASSERT) +# if (LZO_CC_AZTECC) +# define LZO_COMPILE_TIME_ASSERT(e) {typedef int __lzo_cta_t[1-!(e)];} +# elif (LZO_CC_DMC || LZO_CC_PACIFICC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC) +# define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break; +# elif (LZO_CC_MSC && (_MSC_VER < 900)) +# define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break; +# elif (LZO_CC_TURBOC && (__TURBOC__ == 0x0295)) +# define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break; +# else +# define LZO_COMPILE_TIME_ASSERT(e) {typedef int __lzo_cta_t[1-2*!(e)];} +# endif +#endif +#if (LZO_ARCH_I086 || LZO_ARCH_I386) && (LZO_OS_DOS16 || LZO_OS_DOS32 || LZO_OS_OS2 || LZO_OS_OS216 || LZO_OS_WIN16 || LZO_OS_WIN32 || LZO_OS_WIN64) +# if (LZO_CC_GNUC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PACIFICC) +# elif (LZO_CC_DMC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC) +# define __lzo_cdecl __cdecl +# define __lzo_cdecl_atexit +# define __lzo_cdecl_main __cdecl +# if (LZO_OS_OS2 && (LZO_CC_DMC || LZO_CC_SYMANTECC)) +# define __lzo_cdecl_qsort __pascal +# elif (LZO_OS_OS2 && (LZO_CC_ZORTECHC)) +# define __lzo_cdecl_qsort _stdcall +# else +# define __lzo_cdecl_qsort __cdecl +# endif +# elif (LZO_CC_WATCOMC) +# define __lzo_cdecl __cdecl +# else +# define __lzo_cdecl __cdecl +# define __lzo_cdecl_atexit __cdecl +# define __lzo_cdecl_main __cdecl +# define __lzo_cdecl_qsort __cdecl +# endif +# if (LZO_CC_GNUC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PACIFICC || LZO_CC_WATCOMC) +# elif (LZO_OS_OS2 && (LZO_CC_DMC || LZO_CC_SYMANTECC)) +# define __lzo_cdecl_sighandler __pascal +# elif (LZO_OS_OS2 && (LZO_CC_ZORTECHC)) +# define __lzo_cdecl_sighandler _stdcall +# elif (LZO_CC_MSC && (_MSC_VER >= 1400)) && defined(_M_CEE_PURE) +# define __lzo_cdecl_sighandler __clrcall +# elif (LZO_CC_MSC && (_MSC_VER >= 600 && _MSC_VER < 700)) +# if defined(_DLL) +# define __lzo_cdecl_sighandler _far _cdecl _loadds +# elif defined(_MT) +# define __lzo_cdecl_sighandler _far _cdecl +# else +# define __lzo_cdecl_sighandler _cdecl +# endif +# else +# define __lzo_cdecl_sighandler __cdecl +# endif +#elif (LZO_ARCH_I386) && (LZO_CC_WATCOMC) +# define __lzo_cdecl __cdecl +#elif (LZO_ARCH_M68K && LZO_OS_TOS && (LZO_CC_PUREC || LZO_CC_TURBOC)) +# define __lzo_cdecl cdecl +#endif +#if !defined(__lzo_cdecl) +# define __lzo_cdecl +#endif +#if !defined(__lzo_cdecl_atexit) +# define __lzo_cdecl_atexit +#endif +#if !defined(__lzo_cdecl_main) +# define __lzo_cdecl_main +#endif +#if !defined(__lzo_cdecl_qsort) +# define __lzo_cdecl_qsort +#endif +#if !defined(__lzo_cdecl_sighandler) +# define __lzo_cdecl_sighandler +#endif +#if !defined(__lzo_cdecl_va) +# define __lzo_cdecl_va __lzo_cdecl +#endif +#if !defined(LZO_CFG_NO_WINDOWS_H) +#if (LZO_OS_CYGWIN || (LZO_OS_EMX && defined(__RSXNT__)) || LZO_OS_WIN32 || LZO_OS_WIN64) +# if (LZO_CC_WATCOMC && (__WATCOMC__ < 1000)) +# elif (LZO_OS_WIN32 && LZO_CC_GNUC) && defined(__PW32__) +# elif ((LZO_OS_CYGWIN || defined(__MINGW32__)) && (LZO_CC_GNUC && (LZO_CC_GNUC < 0x025f00ul))) +# else +# define LZO_HAVE_WINDOWS_H 1 +# endif +#endif +#endif +#if (LZO_ARCH_ALPHA) +# define LZO_OPT_AVOID_UINT_INDEX 1 +# define LZO_OPT_AVOID_SHORT 1 +# define LZO_OPT_AVOID_USHORT 1 +#elif (LZO_ARCH_AMD64) +# define LZO_OPT_AVOID_INT_INDEX 1 +# define LZO_OPT_AVOID_UINT_INDEX 1 +# define LZO_OPT_UNALIGNED16 1 +# define LZO_OPT_UNALIGNED32 1 +# define LZO_OPT_UNALIGNED64 1 +#elif (LZO_ARCH_ARM && LZO_ARCH_ARM_THUMB) +#elif (LZO_ARCH_ARM) +# define LZO_OPT_AVOID_SHORT 1 +# define LZO_OPT_AVOID_USHORT 1 +#elif (LZO_ARCH_CRIS) +# define LZO_OPT_UNALIGNED16 1 +# define LZO_OPT_UNALIGNED32 1 +#elif (LZO_ARCH_I386) +# define LZO_OPT_UNALIGNED16 1 +# define LZO_OPT_UNALIGNED32 1 +#elif (LZO_ARCH_IA64) +# define LZO_OPT_AVOID_INT_INDEX 1 +# define LZO_OPT_AVOID_UINT_INDEX 1 +# define LZO_OPT_PREFER_POSTINC 1 +#elif (LZO_ARCH_M68K) +# define LZO_OPT_PREFER_POSTINC 1 +# define LZO_OPT_PREFER_PREDEC 1 +# if defined(__mc68020__) && !defined(__mcoldfire__) +# define LZO_OPT_UNALIGNED16 1 +# define LZO_OPT_UNALIGNED32 1 +# endif +#elif (LZO_ARCH_MIPS) +# define LZO_OPT_AVOID_UINT_INDEX 1 +#elif (LZO_ARCH_POWERPC) +# define LZO_OPT_PREFER_PREINC 1 +# define LZO_OPT_PREFER_PREDEC 1 +# if defined(LZO_ABI_BIG_ENDIAN) +# define LZO_OPT_UNALIGNED16 1 +# define LZO_OPT_UNALIGNED32 1 +# endif +#elif (LZO_ARCH_S390) +# define LZO_OPT_UNALIGNED16 1 +# define LZO_OPT_UNALIGNED32 1 +# if (LZO_SIZEOF_SIZE_T == 8) +# define LZO_OPT_UNALIGNED64 1 +# endif +#elif (LZO_ARCH_SH) +# define LZO_OPT_PREFER_POSTINC 1 +# define LZO_OPT_PREFER_PREDEC 1 +#endif +#if !defined(LZO_CFG_NO_INLINE_ASM) +#if defined(LZO_CC_LLVM) +# define LZO_CFG_NO_INLINE_ASM 1 +#endif +#endif +#if !defined(LZO_CFG_NO_UNALIGNED) +#if defined(LZO_ABI_NEUTRAL_ENDIAN) || defined(LZO_ARCH_GENERIC) +# define LZO_CFG_NO_UNALIGNED 1 +#endif +#endif +#if defined(LZO_CFG_NO_UNALIGNED) +# undef LZO_OPT_UNALIGNED16 +# undef LZO_OPT_UNALIGNED32 +# undef LZO_OPT_UNALIGNED64 +#endif +#if defined(LZO_CFG_NO_INLINE_ASM) +#elif (LZO_ARCH_I386 && (LZO_OS_DOS32 || LZO_OS_WIN32) && (LZO_CC_DMC || LZO_CC_INTELC || LZO_CC_MSC || LZO_CC_PELLESC)) +# define LZO_ASM_SYNTAX_MSC 1 +#elif (LZO_OS_WIN64 && (LZO_CC_DMC || LZO_CC_INTELC || LZO_CC_MSC || LZO_CC_PELLESC)) +#elif (LZO_ARCH_I386 && (LZO_CC_GNUC || LZO_CC_INTELC || LZO_CC_PATHSCALE)) +# define LZO_ASM_SYNTAX_GNUC 1 +#elif (LZO_ARCH_AMD64 && (LZO_CC_GNUC || LZO_CC_INTELC || LZO_CC_PATHSCALE)) +# define LZO_ASM_SYNTAX_GNUC 1 +#endif +#if (LZO_ASM_SYNTAX_GNUC) +#if (LZO_ARCH_I386 && LZO_CC_GNUC && (LZO_CC_GNUC < 0x020000ul)) +# define __LZO_ASM_CLOBBER "ax" +#elif (LZO_CC_INTELC) +# define __LZO_ASM_CLOBBER "memory" +#else +# define __LZO_ASM_CLOBBER "cc", "memory" +#endif +#endif +#if defined(__LZO_INFOSTR_MM) +#elif (LZO_MM_FLAT) && (defined(__LZO_INFOSTR_PM) || defined(LZO_INFO_ABI_PM)) +# define __LZO_INFOSTR_MM "" +#elif defined(LZO_INFO_MM) +# define __LZO_INFOSTR_MM "." LZO_INFO_MM +#else +# define __LZO_INFOSTR_MM "" +#endif +#if defined(__LZO_INFOSTR_PM) +#elif defined(LZO_INFO_ABI_PM) +# define __LZO_INFOSTR_PM "." LZO_INFO_ABI_PM +#else +# define __LZO_INFOSTR_PM "" +#endif +#if defined(__LZO_INFOSTR_ENDIAN) +#elif defined(LZO_INFO_ABI_ENDIAN) +# define __LZO_INFOSTR_ENDIAN "." LZO_INFO_ABI_ENDIAN +#else +# define __LZO_INFOSTR_ENDIAN "" +#endif +#if defined(__LZO_INFOSTR_OSNAME) +#elif defined(LZO_INFO_OS_CONSOLE) +# define __LZO_INFOSTR_OSNAME LZO_INFO_OS "." LZO_INFO_OS_CONSOLE +#elif defined(LZO_INFO_OS_POSIX) +# define __LZO_INFOSTR_OSNAME LZO_INFO_OS "." LZO_INFO_OS_POSIX +#else +# define __LZO_INFOSTR_OSNAME LZO_INFO_OS +#endif +#if defined(__LZO_INFOSTR_LIBC) +#elif defined(LZO_INFO_LIBC) +# define __LZO_INFOSTR_LIBC "." LZO_INFO_LIBC +#else +# define __LZO_INFOSTR_LIBC "" +#endif +#if defined(__LZO_INFOSTR_CCVER) +#elif defined(LZO_INFO_CCVER) +# define __LZO_INFOSTR_CCVER " " LZO_INFO_CCVER +#else +# define __LZO_INFOSTR_CCVER "" +#endif +#define LZO_INFO_STRING \ + LZO_INFO_ARCH __LZO_INFOSTR_MM __LZO_INFOSTR_PM __LZO_INFOSTR_ENDIAN \ + " " __LZO_INFOSTR_OSNAME __LZO_INFOSTR_LIBC " " LZO_INFO_CC __LZO_INFOSTR_CCVER + +#endif /* already included */ + +/* vim:set ts=4 et: */ diff --git a/minilzo.c b/minilzo.c new file mode 100644 index 0000000..6a62b31 --- /dev/null +++ b/minilzo.c @@ -0,0 +1,4112 @@ +/* minilzo.c -- mini subset of the LZO real-time data compression library + + This file is part of the LZO real-time data compression library. + + Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer + All Rights Reserved. + + The LZO library is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + The LZO 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with the LZO library; see the file COPYING. + If not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + Markus F.X.J. Oberhumer + + http://www.oberhumer.com/opensource/lzo/ + */ + +/* + * NOTE: + * the full LZO package can be found at + * http://www.oberhumer.com/opensource/lzo/ + */ + +#define __LZO_IN_MINILZO +#define LZO_BUILD + +#if defined(LZO_CFG_FREESTANDING) +# undef MINILZO_HAVE_CONFIG_H +# define LZO_LIBC_FREESTANDING 1 +# define LZO_OS_FREESTANDING 1 +#endif + +#ifdef MINILZO_HAVE_CONFIG_H +# include +#endif +#include +#include +#if defined(MINILZO_CFG_USE_INTERNAL_LZODEFS) + +#ifndef __LZODEFS_H_INCLUDED +#define __LZODEFS_H_INCLUDED 1 + +#if defined(__CYGWIN32__) && !defined(__CYGWIN__) +# define __CYGWIN__ __CYGWIN32__ +#endif +#if defined(__IBMCPP__) && !defined(__IBMC__) +# define __IBMC__ __IBMCPP__ +#endif +#if defined(__ICL) && defined(_WIN32) && !defined(__INTEL_COMPILER) +# define __INTEL_COMPILER __ICL +#endif +#if 1 && defined(__INTERIX) && defined(__GNUC__) && !defined(_ALL_SOURCE) +# define _ALL_SOURCE 1 +#endif +#if defined(__mips__) && defined(__R5900__) +# if !defined(__LONG_MAX__) +# define __LONG_MAX__ 9223372036854775807L +# endif +#endif +#if defined(__INTEL_COMPILER) && defined(__linux__) +# pragma warning(disable: 193) +#endif +#if defined(__KEIL__) && defined(__C166__) +# pragma warning disable = 322 +#elif 0 && defined(__C251__) +# pragma warning disable = 322 +#endif +#if defined(_MSC_VER) && !defined(__INTEL_COMPILER) && !defined(__MWERKS__) +# if (_MSC_VER >= 1300) +# pragma warning(disable: 4668) +# endif +#endif +#if 0 && defined(__WATCOMC__) +# if (__WATCOMC__ >= 1050) && (__WATCOMC__ < 1060) +# pragma warning 203 9 +# endif +#endif +#if defined(__BORLANDC__) && defined(__MSDOS__) && !defined(__FLAT__) +# pragma option -h +#endif +#if 0 +#define LZO_0xffffL 0xfffful +#define LZO_0xffffffffL 0xfffffffful +#else +#define LZO_0xffffL 65535ul +#define LZO_0xffffffffL 4294967295ul +#endif +#if (LZO_0xffffL == LZO_0xffffffffL) +# error "your preprocessor is broken 1" +#endif +#if (16ul * 16384ul != 262144ul) +# error "your preprocessor is broken 2" +#endif +#if 0 +#if (32767 >= 4294967295ul) +# error "your preprocessor is broken 3" +#endif +#if (65535u >= 4294967295ul) +# error "your preprocessor is broken 4" +#endif +#endif +#if (UINT_MAX == LZO_0xffffL) +#if defined(__ZTC__) && defined(__I86__) && !defined(__OS2__) +# if !defined(MSDOS) +# define MSDOS 1 +# endif +# if !defined(_MSDOS) +# define _MSDOS 1 +# endif +#elif 0 && defined(__VERSION) && defined(MB_LEN_MAX) +# if (__VERSION == 520) && (MB_LEN_MAX == 1) +# if !defined(__AZTEC_C__) +# define __AZTEC_C__ __VERSION +# endif +# if !defined(__DOS__) +# define __DOS__ 1 +# endif +# endif +#endif +#endif +#if defined(_MSC_VER) && defined(M_I86HM) && (UINT_MAX == LZO_0xffffL) +# define ptrdiff_t long +# define _PTRDIFF_T_DEFINED +#endif +#if (UINT_MAX == LZO_0xffffL) +# undef __LZO_RENAME_A +# undef __LZO_RENAME_B +# if defined(__AZTEC_C__) && defined(__DOS__) +# define __LZO_RENAME_A 1 +# elif defined(_MSC_VER) && defined(MSDOS) +# if (_MSC_VER < 600) +# define __LZO_RENAME_A 1 +# elif (_MSC_VER < 700) +# define __LZO_RENAME_B 1 +# endif +# elif defined(__TSC__) && defined(__OS2__) +# define __LZO_RENAME_A 1 +# elif defined(__MSDOS__) && defined(__TURBOC__) && (__TURBOC__ < 0x0410) +# define __LZO_RENAME_A 1 +# elif defined(__PACIFIC__) && defined(DOS) +# if !defined(__far) +# define __far far +# endif +# if !defined(__near) +# define __near near +# endif +# endif +# if defined(__LZO_RENAME_A) +# if !defined(__cdecl) +# define __cdecl cdecl +# endif +# if !defined(__far) +# define __far far +# endif +# if !defined(__huge) +# define __huge huge +# endif +# if !defined(__near) +# define __near near +# endif +# if !defined(__pascal) +# define __pascal pascal +# endif +# if !defined(__huge) +# define __huge huge +# endif +# elif defined(__LZO_RENAME_B) +# if !defined(__cdecl) +# define __cdecl _cdecl +# endif +# if !defined(__far) +# define __far _far +# endif +# if !defined(__huge) +# define __huge _huge +# endif +# if !defined(__near) +# define __near _near +# endif +# if !defined(__pascal) +# define __pascal _pascal +# endif +# elif (defined(__PUREC__) || defined(__TURBOC__)) && defined(__TOS__) +# if !defined(__cdecl) +# define __cdecl cdecl +# endif +# if !defined(__pascal) +# define __pascal pascal +# endif +# endif +# undef __LZO_RENAME_A +# undef __LZO_RENAME_B +#endif +#if (UINT_MAX == LZO_0xffffL) +#if defined(__AZTEC_C__) && defined(__DOS__) +# define LZO_BROKEN_CDECL_ALT_SYNTAX 1 +#elif defined(_MSC_VER) && defined(MSDOS) +# if (_MSC_VER < 600) +# define LZO_BROKEN_INTEGRAL_CONSTANTS 1 +# endif +# if (_MSC_VER < 700) +# define LZO_BROKEN_INTEGRAL_PROMOTION 1 +# define LZO_BROKEN_SIZEOF 1 +# endif +#elif defined(__PACIFIC__) && defined(DOS) +# define LZO_BROKEN_INTEGRAL_CONSTANTS 1 +#elif defined(__TURBOC__) && defined(__MSDOS__) +# if (__TURBOC__ < 0x0150) +# define LZO_BROKEN_CDECL_ALT_SYNTAX 1 +# define LZO_BROKEN_INTEGRAL_CONSTANTS 1 +# define LZO_BROKEN_INTEGRAL_PROMOTION 1 +# endif +# if (__TURBOC__ < 0x0200) +# define LZO_BROKEN_SIZEOF 1 +# endif +# if (__TURBOC__ < 0x0400) && defined(__cplusplus) +# define LZO_BROKEN_CDECL_ALT_SYNTAX 1 +# endif +#elif (defined(__PUREC__) || defined(__TURBOC__)) && defined(__TOS__) +# define LZO_BROKEN_CDECL_ALT_SYNTAX 1 +# define LZO_BROKEN_SIZEOF 1 +#endif +#endif +#if defined(__WATCOMC__) && (__WATCOMC__ < 900) +# define LZO_BROKEN_INTEGRAL_CONSTANTS 1 +#endif +#if defined(_CRAY) && defined(_CRAY1) +# define LZO_BROKEN_SIGNED_RIGHT_SHIFT 1 +#endif +#define LZO_PP_STRINGIZE(x) #x +#define LZO_PP_MACRO_EXPAND(x) LZO_PP_STRINGIZE(x) +#define LZO_PP_CONCAT2(a,b) a ## b +#define LZO_PP_CONCAT3(a,b,c) a ## b ## c +#define LZO_PP_CONCAT4(a,b,c,d) a ## b ## c ## d +#define LZO_PP_CONCAT5(a,b,c,d,e) a ## b ## c ## d ## e +#define LZO_PP_ECONCAT2(a,b) LZO_PP_CONCAT2(a,b) +#define LZO_PP_ECONCAT3(a,b,c) LZO_PP_CONCAT3(a,b,c) +#define LZO_PP_ECONCAT4(a,b,c,d) LZO_PP_CONCAT4(a,b,c,d) +#define LZO_PP_ECONCAT5(a,b,c,d,e) LZO_PP_CONCAT5(a,b,c,d,e) +#if 1 +#define LZO_CPP_STRINGIZE(x) #x +#define LZO_CPP_MACRO_EXPAND(x) LZO_CPP_STRINGIZE(x) +#define LZO_CPP_CONCAT2(a,b) a ## b +#define LZO_CPP_CONCAT3(a,b,c) a ## b ## c +#define LZO_CPP_CONCAT4(a,b,c,d) a ## b ## c ## d +#define LZO_CPP_CONCAT5(a,b,c,d,e) a ## b ## c ## d ## e +#define LZO_CPP_ECONCAT2(a,b) LZO_CPP_CONCAT2(a,b) +#define LZO_CPP_ECONCAT3(a,b,c) LZO_CPP_CONCAT3(a,b,c) +#define LZO_CPP_ECONCAT4(a,b,c,d) LZO_CPP_CONCAT4(a,b,c,d) +#define LZO_CPP_ECONCAT5(a,b,c,d,e) LZO_CPP_CONCAT5(a,b,c,d,e) +#endif +#define __LZO_MASK_GEN(o,b) (((((o) << ((b)-1)) - (o)) << 1) + (o)) +#if 1 && defined(__cplusplus) +# if !defined(__STDC_CONSTANT_MACROS) +# define __STDC_CONSTANT_MACROS 1 +# endif +# if !defined(__STDC_LIMIT_MACROS) +# define __STDC_LIMIT_MACROS 1 +# endif +#endif +#if defined(__cplusplus) +# define LZO_EXTERN_C extern "C" +#else +# define LZO_EXTERN_C extern +#endif +#if !defined(__LZO_OS_OVERRIDE) +#if defined(LZO_OS_FREESTANDING) +# define LZO_INFO_OS "freestanding" +#elif defined(LZO_OS_EMBEDDED) +# define LZO_INFO_OS "embedded" +#elif 1 && defined(__IAR_SYSTEMS_ICC__) +# define LZO_OS_EMBEDDED 1 +# define LZO_INFO_OS "embedded" +#elif defined(__CYGWIN__) && defined(__GNUC__) +# define LZO_OS_CYGWIN 1 +# define LZO_INFO_OS "cygwin" +#elif defined(__EMX__) && defined(__GNUC__) +# define LZO_OS_EMX 1 +# define LZO_INFO_OS "emx" +#elif defined(__BEOS__) +# define LZO_OS_BEOS 1 +# define LZO_INFO_OS "beos" +#elif defined(__Lynx__) +# define LZO_OS_LYNXOS 1 +# define LZO_INFO_OS "lynxos" +#elif defined(__OS400__) +# define LZO_OS_OS400 1 +# define LZO_INFO_OS "os400" +#elif defined(__QNX__) +# define LZO_OS_QNX 1 +# define LZO_INFO_OS "qnx" +#elif defined(__BORLANDC__) && defined(__DPMI32__) && (__BORLANDC__ >= 0x0460) +# define LZO_OS_DOS32 1 +# define LZO_INFO_OS "dos32" +#elif defined(__BORLANDC__) && defined(__DPMI16__) +# define LZO_OS_DOS16 1 +# define LZO_INFO_OS "dos16" +#elif defined(__ZTC__) && defined(DOS386) +# define LZO_OS_DOS32 1 +# define LZO_INFO_OS "dos32" +#elif defined(__OS2__) || defined(__OS2V2__) +# if (UINT_MAX == LZO_0xffffL) +# define LZO_OS_OS216 1 +# define LZO_INFO_OS "os216" +# elif (UINT_MAX == LZO_0xffffffffL) +# define LZO_OS_OS2 1 +# define LZO_INFO_OS "os2" +# else +# error "check your limits.h header" +# endif +#elif defined(__WIN64__) || defined(_WIN64) || defined(WIN64) +# define LZO_OS_WIN64 1 +# define LZO_INFO_OS "win64" +#elif defined(__WIN32__) || defined(_WIN32) || defined(WIN32) || defined(__WINDOWS_386__) +# define LZO_OS_WIN32 1 +# define LZO_INFO_OS "win32" +#elif defined(__MWERKS__) && defined(__INTEL__) +# define LZO_OS_WIN32 1 +# define LZO_INFO_OS "win32" +#elif defined(__WINDOWS__) || defined(_WINDOWS) || defined(_Windows) +# if (UINT_MAX == LZO_0xffffL) +# define LZO_OS_WIN16 1 +# define LZO_INFO_OS "win16" +# elif (UINT_MAX == LZO_0xffffffffL) +# define LZO_OS_WIN32 1 +# define LZO_INFO_OS "win32" +# else +# error "check your limits.h header" +# endif +#elif defined(__DOS__) || defined(__MSDOS__) || defined(_MSDOS) || defined(MSDOS) || (defined(__PACIFIC__) && defined(DOS)) +# if (UINT_MAX == LZO_0xffffL) +# define LZO_OS_DOS16 1 +# define LZO_INFO_OS "dos16" +# elif (UINT_MAX == LZO_0xffffffffL) +# define LZO_OS_DOS32 1 +# define LZO_INFO_OS "dos32" +# else +# error "check your limits.h header" +# endif +#elif defined(__WATCOMC__) +# if defined(__NT__) && (UINT_MAX == LZO_0xffffL) +# define LZO_OS_DOS16 1 +# define LZO_INFO_OS "dos16" +# elif defined(__NT__) && (__WATCOMC__ < 1100) +# define LZO_OS_WIN32 1 +# define LZO_INFO_OS "win32" +# elif defined(__linux__) || defined(__LINUX__) +# define LZO_OS_POSIX 1 +# define LZO_INFO_OS "posix" +# else +# error "please specify a target using the -bt compiler option" +# endif +#elif defined(__palmos__) +# define LZO_OS_PALMOS 1 +# define LZO_INFO_OS "palmos" +#elif defined(__TOS__) || defined(__atarist__) +# define LZO_OS_TOS 1 +# define LZO_INFO_OS "tos" +#elif defined(macintosh) && !defined(__ppc__) +# define LZO_OS_MACCLASSIC 1 +# define LZO_INFO_OS "macclassic" +#elif defined(__VMS) +# define LZO_OS_VMS 1 +# define LZO_INFO_OS "vms" +#elif ((defined(__mips__) && defined(__R5900__)) || defined(__MIPS_PSX2__)) +# define LZO_OS_CONSOLE 1 +# define LZO_OS_CONSOLE_PS2 1 +# define LZO_INFO_OS "console" +# define LZO_INFO_OS_CONSOLE "ps2" +#elif (defined(__mips__) && defined(__psp__)) +# define LZO_OS_CONSOLE 1 +# define LZO_OS_CONSOLE_PSP 1 +# define LZO_INFO_OS "console" +# define LZO_INFO_OS_CONSOLE "psp" +#else +# define LZO_OS_POSIX 1 +# define LZO_INFO_OS "posix" +#endif +#if (LZO_OS_POSIX) +# if defined(_AIX) || defined(__AIX__) || defined(__aix__) +# define LZO_OS_POSIX_AIX 1 +# define LZO_INFO_OS_POSIX "aix" +# elif defined(__FreeBSD__) +# define LZO_OS_POSIX_FREEBSD 1 +# define LZO_INFO_OS_POSIX "freebsd" +# elif defined(__hpux__) || defined(__hpux) +# define LZO_OS_POSIX_HPUX 1 +# define LZO_INFO_OS_POSIX "hpux" +# elif defined(__INTERIX) +# define LZO_OS_POSIX_INTERIX 1 +# define LZO_INFO_OS_POSIX "interix" +# elif defined(__IRIX__) || defined(__irix__) +# define LZO_OS_POSIX_IRIX 1 +# define LZO_INFO_OS_POSIX "irix" +# elif defined(__linux__) || defined(__linux) || defined(__LINUX__) +# define LZO_OS_POSIX_LINUX 1 +# define LZO_INFO_OS_POSIX "linux" +# elif defined(__APPLE__) || defined(__MACOS__) +# define LZO_OS_POSIX_MACOSX 1 +# define LZO_INFO_OS_POSIX "macosx" +# elif defined(__minix__) || defined(__minix) +# define LZO_OS_POSIX_MINIX 1 +# define LZO_INFO_OS_POSIX "minix" +# elif defined(__NetBSD__) +# define LZO_OS_POSIX_NETBSD 1 +# define LZO_INFO_OS_POSIX "netbsd" +# elif defined(__OpenBSD__) +# define LZO_OS_POSIX_OPENBSD 1 +# define LZO_INFO_OS_POSIX "openbsd" +# elif defined(__osf__) +# define LZO_OS_POSIX_OSF 1 +# define LZO_INFO_OS_POSIX "osf" +# elif defined(__solaris__) || defined(__sun) +# if defined(__SVR4) || defined(__svr4__) +# define LZO_OS_POSIX_SOLARIS 1 +# define LZO_INFO_OS_POSIX "solaris" +# else +# define LZO_OS_POSIX_SUNOS 1 +# define LZO_INFO_OS_POSIX "sunos" +# endif +# elif defined(__ultrix__) || defined(__ultrix) +# define LZO_OS_POSIX_ULTRIX 1 +# define LZO_INFO_OS_POSIX "ultrix" +# elif defined(_UNICOS) +# define LZO_OS_POSIX_UNICOS 1 +# define LZO_INFO_OS_POSIX "unicos" +# else +# define LZO_OS_POSIX_UNKNOWN 1 +# define LZO_INFO_OS_POSIX "unknown" +# endif +#endif +#endif +#if (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16) +# if (UINT_MAX != LZO_0xffffL) +# error "this should not happen" +# endif +# if (ULONG_MAX != LZO_0xffffffffL) +# error "this should not happen" +# endif +#endif +#if (LZO_OS_DOS32 || LZO_OS_OS2 || LZO_OS_WIN32 || LZO_OS_WIN64) +# if (UINT_MAX != LZO_0xffffffffL) +# error "this should not happen" +# endif +# if (ULONG_MAX != LZO_0xffffffffL) +# error "this should not happen" +# endif +#endif +#if defined(CIL) && defined(_GNUCC) && defined(__GNUC__) +# define LZO_CC_CILLY 1 +# define LZO_INFO_CC "Cilly" +# if defined(__CILLY__) +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__CILLY__) +# else +# define LZO_INFO_CCVER "unknown" +# endif +#elif 0 && defined(SDCC) && defined(__VERSION__) && !defined(__GNUC__) +# define LZO_CC_SDCC 1 +# define LZO_INFO_CC "sdcc" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(SDCC) +#elif defined(__PATHSCALE__) && defined(__PATHCC_PATCHLEVEL__) +# define LZO_CC_PATHSCALE (__PATHCC__ * 0x10000L + __PATHCC_MINOR__ * 0x100 + __PATHCC_PATCHLEVEL__) +# define LZO_INFO_CC "Pathscale C" +# define LZO_INFO_CCVER __PATHSCALE__ +#elif defined(__INTEL_COMPILER) +# define LZO_CC_INTELC 1 +# define LZO_INFO_CC "Intel C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__INTEL_COMPILER) +# if defined(_WIN32) || defined(_WIN64) +# define LZO_CC_SYNTAX_MSC 1 +# else +# define LZO_CC_SYNTAX_GNUC 1 +# endif +#elif defined(__POCC__) && defined(_WIN32) +# define LZO_CC_PELLESC 1 +# define LZO_INFO_CC "Pelles C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__POCC__) +#elif defined(__llvm__) && defined(__GNUC__) && defined(__VERSION__) +# if defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__) +# define LZO_CC_LLVM (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100 + __GNUC_PATCHLEVEL__) +# else +# define LZO_CC_LLVM (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100) +# endif +# define LZO_INFO_CC "llvm-gcc" +# define LZO_INFO_CCVER __VERSION__ +#elif defined(__GNUC__) && defined(__VERSION__) +# if defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__) +# define LZO_CC_GNUC (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100 + __GNUC_PATCHLEVEL__) +# elif defined(__GNUC_MINOR__) +# define LZO_CC_GNUC (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100) +# else +# define LZO_CC_GNUC (__GNUC__ * 0x10000L) +# endif +# define LZO_INFO_CC "gcc" +# define LZO_INFO_CCVER __VERSION__ +#elif defined(__ACK__) && defined(_ACK) +# define LZO_CC_ACK 1 +# define LZO_INFO_CC "Amsterdam Compiler Kit C" +# define LZO_INFO_CCVER "unknown" +#elif defined(__AZTEC_C__) +# define LZO_CC_AZTECC 1 +# define LZO_INFO_CC "Aztec C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__AZTEC_C__) +#elif defined(__BORLANDC__) +# define LZO_CC_BORLANDC 1 +# define LZO_INFO_CC "Borland C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__BORLANDC__) +#elif defined(_CRAYC) && defined(_RELEASE) +# define LZO_CC_CRAYC 1 +# define LZO_INFO_CC "Cray C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(_RELEASE) +#elif defined(__DMC__) && defined(__SC__) +# define LZO_CC_DMC 1 +# define LZO_INFO_CC "Digital Mars C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__DMC__) +#elif defined(__DECC) +# define LZO_CC_DECC 1 +# define LZO_INFO_CC "DEC C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__DECC) +#elif defined(__HIGHC__) +# define LZO_CC_HIGHC 1 +# define LZO_INFO_CC "MetaWare High C" +# define LZO_INFO_CCVER "unknown" +#elif defined(__IAR_SYSTEMS_ICC__) +# define LZO_CC_IARC 1 +# define LZO_INFO_CC "IAR C" +# if defined(__VER__) +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__VER__) +# else +# define LZO_INFO_CCVER "unknown" +# endif +#elif defined(__IBMC__) +# define LZO_CC_IBMC 1 +# define LZO_INFO_CC "IBM C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__IBMC__) +#elif defined(__KEIL__) && defined(__C166__) +# define LZO_CC_KEILC 1 +# define LZO_INFO_CC "Keil C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__C166__) +#elif defined(__LCC__) && defined(_WIN32) && defined(__LCCOPTIMLEVEL) +# define LZO_CC_LCCWIN32 1 +# define LZO_INFO_CC "lcc-win32" +# define LZO_INFO_CCVER "unknown" +#elif defined(__LCC__) +# define LZO_CC_LCC 1 +# define LZO_INFO_CC "lcc" +# if defined(__LCC_VERSION__) +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__LCC_VERSION__) +# else +# define LZO_INFO_CCVER "unknown" +# endif +#elif defined(_MSC_VER) +# define LZO_CC_MSC 1 +# define LZO_INFO_CC "Microsoft C" +# if defined(_MSC_FULL_VER) +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(_MSC_VER) "." LZO_PP_MACRO_EXPAND(_MSC_FULL_VER) +# else +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(_MSC_VER) +# endif +#elif defined(__MWERKS__) +# define LZO_CC_MWERKS 1 +# define LZO_INFO_CC "Metrowerks C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__MWERKS__) +#elif (defined(__NDPC__) || defined(__NDPX__)) && defined(__i386) +# define LZO_CC_NDPC 1 +# define LZO_INFO_CC "Microway NDP C" +# define LZO_INFO_CCVER "unknown" +#elif defined(__PACIFIC__) +# define LZO_CC_PACIFICC 1 +# define LZO_INFO_CC "Pacific C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__PACIFIC__) +#elif defined(__PGI) && (defined(__linux__) || defined(__WIN32__)) +# define LZO_CC_PGI 1 +# define LZO_INFO_CC "Portland Group PGI C" +# define LZO_INFO_CCVER "unknown" +#elif defined(__PUREC__) && defined(__TOS__) +# define LZO_CC_PUREC 1 +# define LZO_INFO_CC "Pure C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__PUREC__) +#elif defined(__SC__) && defined(__ZTC__) +# define LZO_CC_SYMANTECC 1 +# define LZO_INFO_CC "Symantec C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__SC__) +#elif defined(__SUNPRO_C) +# define LZO_INFO_CC "SunPro C" +# if ((__SUNPRO_C)+0 > 0) +# define LZO_CC_SUNPROC __SUNPRO_C +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__SUNPRO_C) +# else +# define LZO_CC_SUNPROC 1 +# define LZO_INFO_CCVER "unknown" +# endif +#elif defined(__SUNPRO_CC) +# define LZO_INFO_CC "SunPro C" +# if ((__SUNPRO_CC)+0 > 0) +# define LZO_CC_SUNPROC __SUNPRO_CC +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__SUNPRO_CC) +# else +# define LZO_CC_SUNPROC 1 +# define LZO_INFO_CCVER "unknown" +# endif +#elif defined(__TINYC__) +# define LZO_CC_TINYC 1 +# define LZO_INFO_CC "Tiny C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__TINYC__) +#elif defined(__TSC__) +# define LZO_CC_TOPSPEEDC 1 +# define LZO_INFO_CC "TopSpeed C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__TSC__) +#elif defined(__WATCOMC__) +# define LZO_CC_WATCOMC 1 +# define LZO_INFO_CC "Watcom C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__WATCOMC__) +#elif defined(__TURBOC__) +# define LZO_CC_TURBOC 1 +# define LZO_INFO_CC "Turbo C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__TURBOC__) +#elif defined(__ZTC__) +# define LZO_CC_ZORTECHC 1 +# define LZO_INFO_CC "Zortech C" +# if (__ZTC__ == 0x310) +# define LZO_INFO_CCVER "0x310" +# else +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__ZTC__) +# endif +#else +# define LZO_CC_UNKNOWN 1 +# define LZO_INFO_CC "unknown" +# define LZO_INFO_CCVER "unknown" +#endif +#if 0 && (LZO_CC_MSC && (_MSC_VER >= 1200)) && !defined(_MSC_FULL_VER) +# error "LZO_CC_MSC: _MSC_FULL_VER is not defined" +#endif +#if !defined(__LZO_ARCH_OVERRIDE) && !defined(LZO_ARCH_GENERIC) && defined(_CRAY) +# if (UINT_MAX > LZO_0xffffffffL) && defined(_CRAY) +# if defined(_CRAYMPP) || defined(_CRAYT3D) || defined(_CRAYT3E) +# define LZO_ARCH_CRAY_MPP 1 +# elif defined(_CRAY1) +# define LZO_ARCH_CRAY_PVP 1 +# endif +# endif +#endif +#if !defined(__LZO_ARCH_OVERRIDE) +#if defined(LZO_ARCH_GENERIC) +# define LZO_INFO_ARCH "generic" +#elif (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16) +# define LZO_ARCH_I086 1 +# define LZO_ARCH_IA16 1 +# define LZO_INFO_ARCH "i086" +#elif defined(__alpha__) || defined(__alpha) || defined(_M_ALPHA) +# define LZO_ARCH_ALPHA 1 +# define LZO_INFO_ARCH "alpha" +#elif (LZO_ARCH_CRAY_MPP) && (defined(_CRAYT3D) || defined(_CRAYT3E)) +# define LZO_ARCH_ALPHA 1 +# define LZO_INFO_ARCH "alpha" +#elif defined(__amd64__) || defined(__x86_64__) || defined(_M_AMD64) +# define LZO_ARCH_AMD64 1 +# define LZO_INFO_ARCH "amd64" +#elif defined(__thumb__) || (defined(_M_ARM) && defined(_M_THUMB)) +# define LZO_ARCH_ARM 1 +# define LZO_ARCH_ARM_THUMB 1 +# define LZO_INFO_ARCH "arm_thumb" +#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICCARM__) +# define LZO_ARCH_ARM 1 +# if defined(__CPU_MODE__) && ((__CPU_MODE__)+0 == 1) +# define LZO_ARCH_ARM_THUMB 1 +# define LZO_INFO_ARCH "arm_thumb" +# elif defined(__CPU_MODE__) && ((__CPU_MODE__)+0 == 2) +# define LZO_INFO_ARCH "arm" +# else +# define LZO_INFO_ARCH "arm" +# endif +#elif defined(__arm__) || defined(_M_ARM) +# define LZO_ARCH_ARM 1 +# define LZO_INFO_ARCH "arm" +#elif (UINT_MAX <= LZO_0xffffL) && defined(__AVR__) +# define LZO_ARCH_AVR 1 +# define LZO_INFO_ARCH "avr" +#elif defined(__bfin__) +# define LZO_ARCH_BLACKFIN 1 +# define LZO_INFO_ARCH "blackfin" +#elif (UINT_MAX == LZO_0xffffL) && defined(__C166__) +# define LZO_ARCH_C166 1 +# define LZO_INFO_ARCH "c166" +#elif defined(__cris__) +# define LZO_ARCH_CRIS 1 +# define LZO_INFO_ARCH "cris" +#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICCEZ80__) +# define LZO_ARCH_EZ80 1 +# define LZO_INFO_ARCH "ez80" +#elif defined(__H8300__) || defined(__H8300H__) || defined(__H8300S__) || defined(__H8300SX__) +# define LZO_ARCH_H8300 1 +# define LZO_INFO_ARCH "h8300" +#elif defined(__hppa__) || defined(__hppa) +# define LZO_ARCH_HPPA 1 +# define LZO_INFO_ARCH "hppa" +#elif defined(__386__) || defined(__i386__) || defined(__i386) || defined(_M_IX86) || defined(_M_I386) +# define LZO_ARCH_I386 1 +# define LZO_ARCH_IA32 1 +# define LZO_INFO_ARCH "i386" +#elif (LZO_CC_ZORTECHC && defined(__I86__)) +# define LZO_ARCH_I386 1 +# define LZO_ARCH_IA32 1 +# define LZO_INFO_ARCH "i386" +#elif (LZO_OS_DOS32 && LZO_CC_HIGHC) && defined(_I386) +# define LZO_ARCH_I386 1 +# define LZO_ARCH_IA32 1 +# define LZO_INFO_ARCH "i386" +#elif defined(__ia64__) || defined(__ia64) || defined(_M_IA64) +# define LZO_ARCH_IA64 1 +# define LZO_INFO_ARCH "ia64" +#elif (UINT_MAX == LZO_0xffffL) && defined(__m32c__) +# define LZO_ARCH_M16C 1 +# define LZO_INFO_ARCH "m16c" +#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICCM16C__) +# define LZO_ARCH_M16C 1 +# define LZO_INFO_ARCH "m16c" +#elif defined(__m32r__) +# define LZO_ARCH_M32R 1 +# define LZO_INFO_ARCH "m32r" +#elif (LZO_OS_TOS) || defined(__m68k__) || defined(__m68000__) || defined(__mc68000__) || defined(__mc68020__) || defined(_M_M68K) +# define LZO_ARCH_M68K 1 +# define LZO_INFO_ARCH "m68k" +#elif (UINT_MAX == LZO_0xffffL) && defined(__C251__) +# define LZO_ARCH_MCS251 1 +# define LZO_INFO_ARCH "mcs251" +#elif (UINT_MAX == LZO_0xffffL) && defined(__C51__) +# define LZO_ARCH_MCS51 1 +# define LZO_INFO_ARCH "mcs51" +#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICC8051__) +# define LZO_ARCH_MCS51 1 +# define LZO_INFO_ARCH "mcs51" +#elif defined(__mips__) || defined(__mips) || defined(_MIPS_ARCH) || defined(_M_MRX000) +# define LZO_ARCH_MIPS 1 +# define LZO_INFO_ARCH "mips" +#elif (UINT_MAX == LZO_0xffffL) && defined(__MSP430__) +# define LZO_ARCH_MSP430 1 +# define LZO_INFO_ARCH "msp430" +#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICC430__) +# define LZO_ARCH_MSP430 1 +# define LZO_INFO_ARCH "msp430" +#elif defined(__powerpc__) || defined(__powerpc) || defined(__ppc__) || defined(__PPC__) || defined(_M_PPC) || defined(_ARCH_PPC) || defined(_ARCH_PWR) +# define LZO_ARCH_POWERPC 1 +# define LZO_INFO_ARCH "powerpc" +#elif defined(__s390__) || defined(__s390) || defined(__s390x__) || defined(__s390x) +# define LZO_ARCH_S390 1 +# define LZO_INFO_ARCH "s390" +#elif defined(__sh__) || defined(_M_SH) +# define LZO_ARCH_SH 1 +# define LZO_INFO_ARCH "sh" +#elif defined(__sparc__) || defined(__sparc) || defined(__sparcv8) +# define LZO_ARCH_SPARC 1 +# define LZO_INFO_ARCH "sparc" +#elif defined(__SPU__) +# define LZO_ARCH_SPU 1 +# define LZO_INFO_ARCH "spu" +#elif (UINT_MAX == LZO_0xffffL) && defined(__z80) +# define LZO_ARCH_Z80 1 +# define LZO_INFO_ARCH "z80" +#elif (LZO_ARCH_CRAY_PVP) +# if defined(_CRAYSV1) +# define LZO_ARCH_CRAY_SV1 1 +# define LZO_INFO_ARCH "cray_sv1" +# elif (_ADDR64) +# define LZO_ARCH_CRAY_T90 1 +# define LZO_INFO_ARCH "cray_t90" +# elif (_ADDR32) +# define LZO_ARCH_CRAY_YMP 1 +# define LZO_INFO_ARCH "cray_ymp" +# else +# define LZO_ARCH_CRAY_XMP 1 +# define LZO_INFO_ARCH "cray_xmp" +# endif +#else +# define LZO_ARCH_UNKNOWN 1 +# define LZO_INFO_ARCH "unknown" +#endif +#endif +#if 1 && (LZO_ARCH_UNKNOWN) && (LZO_OS_DOS32 || LZO_OS_OS2) +# error "FIXME - missing define for CPU architecture" +#endif +#if 1 && (LZO_ARCH_UNKNOWN) && (LZO_OS_WIN32) +# error "FIXME - missing WIN32 define for CPU architecture" +#endif +#if 1 && (LZO_ARCH_UNKNOWN) && (LZO_OS_WIN64) +# error "FIXME - missing WIN64 define for CPU architecture" +#endif +#if (LZO_OS_OS216 || LZO_OS_WIN16) +# define LZO_ARCH_I086PM 1 +# define LZO_ARCH_IA16PM 1 +#elif 1 && (LZO_OS_DOS16 && defined(BLX286)) +# define LZO_ARCH_I086PM 1 +# define LZO_ARCH_IA16PM 1 +#elif 1 && (LZO_OS_DOS16 && defined(DOSX286)) +# define LZO_ARCH_I086PM 1 +# define LZO_ARCH_IA16PM 1 +#elif 1 && (LZO_OS_DOS16 && LZO_CC_BORLANDC && defined(__DPMI16__)) +# define LZO_ARCH_I086PM 1 +# define LZO_ARCH_IA16PM 1 +#endif +#if defined(LZO_ARCH_ARM_THUMB) && !defined(LZO_ARCH_ARM) +# error "this should not happen" +#endif +#if defined(LZO_ARCH_I086PM) && !defined(LZO_ARCH_I086) +# error "this should not happen" +#endif +#if (LZO_ARCH_I086) +# if (UINT_MAX != LZO_0xffffL) +# error "this should not happen" +# endif +# if (ULONG_MAX != LZO_0xffffffffL) +# error "this should not happen" +# endif +#endif +#if (LZO_ARCH_I386) +# if (UINT_MAX != LZO_0xffffL) && defined(__i386_int16__) +# error "this should not happen" +# endif +# if (UINT_MAX != LZO_0xffffffffL) && !defined(__i386_int16__) +# error "this should not happen" +# endif +# if (ULONG_MAX != LZO_0xffffffffL) +# error "this should not happen" +# endif +#endif +#if !defined(__LZO_MM_OVERRIDE) +#if (LZO_ARCH_I086) +#if (UINT_MAX != LZO_0xffffL) +# error "this should not happen" +#endif +#if defined(__TINY__) || defined(M_I86TM) || defined(_M_I86TM) +# define LZO_MM_TINY 1 +#elif defined(__HUGE__) || defined(_HUGE_) || defined(M_I86HM) || defined(_M_I86HM) +# define LZO_MM_HUGE 1 +#elif defined(__SMALL__) || defined(M_I86SM) || defined(_M_I86SM) || defined(SMALL_MODEL) +# define LZO_MM_SMALL 1 +#elif defined(__MEDIUM__) || defined(M_I86MM) || defined(_M_I86MM) +# define LZO_MM_MEDIUM 1 +#elif defined(__COMPACT__) || defined(M_I86CM) || defined(_M_I86CM) +# define LZO_MM_COMPACT 1 +#elif defined(__LARGE__) || defined(M_I86LM) || defined(_M_I86LM) || defined(LARGE_MODEL) +# define LZO_MM_LARGE 1 +#elif (LZO_CC_AZTECC) +# if defined(_LARGE_CODE) && defined(_LARGE_DATA) +# define LZO_MM_LARGE 1 +# elif defined(_LARGE_CODE) +# define LZO_MM_MEDIUM 1 +# elif defined(_LARGE_DATA) +# define LZO_MM_COMPACT 1 +# else +# define LZO_MM_SMALL 1 +# endif +#elif (LZO_CC_ZORTECHC && defined(__VCM__)) +# define LZO_MM_LARGE 1 +#else +# error "unknown memory model" +#endif +#if (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16) +#define LZO_HAVE_MM_HUGE_PTR 1 +#define LZO_HAVE_MM_HUGE_ARRAY 1 +#if (LZO_MM_TINY) +# undef LZO_HAVE_MM_HUGE_ARRAY +#endif +#if (LZO_CC_AZTECC || LZO_CC_PACIFICC || LZO_CC_ZORTECHC) +# undef LZO_HAVE_MM_HUGE_PTR +# undef LZO_HAVE_MM_HUGE_ARRAY +#elif (LZO_CC_DMC || LZO_CC_SYMANTECC) +# undef LZO_HAVE_MM_HUGE_ARRAY +#elif (LZO_CC_MSC && defined(_QC)) +# undef LZO_HAVE_MM_HUGE_ARRAY +# if (_MSC_VER < 600) +# undef LZO_HAVE_MM_HUGE_PTR +# endif +#elif (LZO_CC_TURBOC && (__TURBOC__ < 0x0295)) +# undef LZO_HAVE_MM_HUGE_ARRAY +#endif +#if (LZO_ARCH_I086PM) && !defined(LZO_HAVE_MM_HUGE_PTR) +# if (LZO_OS_DOS16) +# error "this should not happen" +# elif (LZO_CC_ZORTECHC) +# else +# error "this should not happen" +# endif +#endif +#ifdef __cplusplus +extern "C" { +#endif +#if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0200)) + extern void __near __cdecl _AHSHIFT(void); +# define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT) +#elif (LZO_CC_DMC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC) + extern void __near __cdecl _AHSHIFT(void); +# define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT) +#elif (LZO_CC_MSC || LZO_CC_TOPSPEEDC) + extern void __near __cdecl _AHSHIFT(void); +# define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT) +#elif (LZO_CC_TURBOC && (__TURBOC__ >= 0x0295)) + extern void __near __cdecl _AHSHIFT(void); +# define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT) +#elif ((LZO_CC_AZTECC || LZO_CC_PACIFICC || LZO_CC_TURBOC) && LZO_OS_DOS16) +# define LZO_MM_AHSHIFT 12 +#elif (LZO_CC_WATCOMC) + extern unsigned char _HShift; +# define LZO_MM_AHSHIFT ((unsigned) _HShift) +#else +# error "FIXME - implement LZO_MM_AHSHIFT" +#endif +#ifdef __cplusplus +} +#endif +#endif +#elif (LZO_ARCH_C166) +#if !defined(__MODEL__) +# error "FIXME - C166 __MODEL__" +#elif ((__MODEL__) == 0) +# define LZO_MM_SMALL 1 +#elif ((__MODEL__) == 1) +# define LZO_MM_SMALL 1 +#elif ((__MODEL__) == 2) +# define LZO_MM_LARGE 1 +#elif ((__MODEL__) == 3) +# define LZO_MM_TINY 1 +#elif ((__MODEL__) == 4) +# define LZO_MM_XTINY 1 +#elif ((__MODEL__) == 5) +# define LZO_MM_XSMALL 1 +#else +# error "FIXME - C166 __MODEL__" +#endif +#elif (LZO_ARCH_MCS251) +#if !defined(__MODEL__) +# error "FIXME - MCS251 __MODEL__" +#elif ((__MODEL__) == 0) +# define LZO_MM_SMALL 1 +#elif ((__MODEL__) == 2) +# define LZO_MM_LARGE 1 +#elif ((__MODEL__) == 3) +# define LZO_MM_TINY 1 +#elif ((__MODEL__) == 4) +# define LZO_MM_XTINY 1 +#elif ((__MODEL__) == 5) +# define LZO_MM_XSMALL 1 +#else +# error "FIXME - MCS251 __MODEL__" +#endif +#elif (LZO_ARCH_MCS51) +#if !defined(__MODEL__) +# error "FIXME - MCS51 __MODEL__" +#elif ((__MODEL__) == 1) +# define LZO_MM_SMALL 1 +#elif ((__MODEL__) == 2) +# define LZO_MM_LARGE 1 +#elif ((__MODEL__) == 3) +# define LZO_MM_TINY 1 +#elif ((__MODEL__) == 4) +# define LZO_MM_XTINY 1 +#elif ((__MODEL__) == 5) +# define LZO_MM_XSMALL 1 +#else +# error "FIXME - MCS51 __MODEL__" +#endif +#elif (LZO_ARCH_CRAY_PVP) +# define LZO_MM_PVP 1 +#else +# define LZO_MM_FLAT 1 +#endif +#if (LZO_MM_COMPACT) +# define LZO_INFO_MM "compact" +#elif (LZO_MM_FLAT) +# define LZO_INFO_MM "flat" +#elif (LZO_MM_HUGE) +# define LZO_INFO_MM "huge" +#elif (LZO_MM_LARGE) +# define LZO_INFO_MM "large" +#elif (LZO_MM_MEDIUM) +# define LZO_INFO_MM "medium" +#elif (LZO_MM_PVP) +# define LZO_INFO_MM "pvp" +#elif (LZO_MM_SMALL) +# define LZO_INFO_MM "small" +#elif (LZO_MM_TINY) +# define LZO_INFO_MM "tiny" +#else +# error "unknown memory model" +#endif +#endif +#if defined(SIZEOF_SHORT) +# define LZO_SIZEOF_SHORT (SIZEOF_SHORT) +#endif +#if defined(SIZEOF_INT) +# define LZO_SIZEOF_INT (SIZEOF_INT) +#endif +#if defined(SIZEOF_LONG) +# define LZO_SIZEOF_LONG (SIZEOF_LONG) +#endif +#if defined(SIZEOF_LONG_LONG) +# define LZO_SIZEOF_LONG_LONG (SIZEOF_LONG_LONG) +#endif +#if defined(SIZEOF___INT16) +# define LZO_SIZEOF___INT16 (SIZEOF___INT16) +#endif +#if defined(SIZEOF___INT32) +# define LZO_SIZEOF___INT32 (SIZEOF___INT32) +#endif +#if defined(SIZEOF___INT64) +# define LZO_SIZEOF___INT64 (SIZEOF___INT64) +#endif +#if defined(SIZEOF_VOID_P) +# define LZO_SIZEOF_VOID_P (SIZEOF_VOID_P) +#endif +#if defined(SIZEOF_SIZE_T) +# define LZO_SIZEOF_SIZE_T (SIZEOF_SIZE_T) +#endif +#if defined(SIZEOF_PTRDIFF_T) +# define LZO_SIZEOF_PTRDIFF_T (SIZEOF_PTRDIFF_T) +#endif +#define __LZO_LSR(x,b) (((x)+0ul) >> (b)) +#if !defined(LZO_SIZEOF_SHORT) +# if (LZO_ARCH_CRAY_PVP) +# define LZO_SIZEOF_SHORT 8 +# elif (USHRT_MAX == LZO_0xffffL) +# define LZO_SIZEOF_SHORT 2 +# elif (__LZO_LSR(USHRT_MAX,7) == 1) +# define LZO_SIZEOF_SHORT 1 +# elif (__LZO_LSR(USHRT_MAX,15) == 1) +# define LZO_SIZEOF_SHORT 2 +# elif (__LZO_LSR(USHRT_MAX,31) == 1) +# define LZO_SIZEOF_SHORT 4 +# elif (__LZO_LSR(USHRT_MAX,63) == 1) +# define LZO_SIZEOF_SHORT 8 +# elif (__LZO_LSR(USHRT_MAX,127) == 1) +# define LZO_SIZEOF_SHORT 16 +# else +# error "LZO_SIZEOF_SHORT" +# endif +#endif +#if !defined(LZO_SIZEOF_INT) +# if (LZO_ARCH_CRAY_PVP) +# define LZO_SIZEOF_INT 8 +# elif (UINT_MAX == LZO_0xffffL) +# define LZO_SIZEOF_INT 2 +# elif (UINT_MAX == LZO_0xffffffffL) +# define LZO_SIZEOF_INT 4 +# elif (__LZO_LSR(UINT_MAX,7) == 1) +# define LZO_SIZEOF_INT 1 +# elif (__LZO_LSR(UINT_MAX,15) == 1) +# define LZO_SIZEOF_INT 2 +# elif (__LZO_LSR(UINT_MAX,31) == 1) +# define LZO_SIZEOF_INT 4 +# elif (__LZO_LSR(UINT_MAX,63) == 1) +# define LZO_SIZEOF_INT 8 +# elif (__LZO_LSR(UINT_MAX,127) == 1) +# define LZO_SIZEOF_INT 16 +# else +# error "LZO_SIZEOF_INT" +# endif +#endif +#if !defined(LZO_SIZEOF_LONG) +# if (ULONG_MAX == LZO_0xffffffffL) +# define LZO_SIZEOF_LONG 4 +# elif (__LZO_LSR(ULONG_MAX,7) == 1) +# define LZO_SIZEOF_LONG 1 +# elif (__LZO_LSR(ULONG_MAX,15) == 1) +# define LZO_SIZEOF_LONG 2 +# elif (__LZO_LSR(ULONG_MAX,31) == 1) +# define LZO_SIZEOF_LONG 4 +# elif (__LZO_LSR(ULONG_MAX,63) == 1) +# define LZO_SIZEOF_LONG 8 +# elif (__LZO_LSR(ULONG_MAX,127) == 1) +# define LZO_SIZEOF_LONG 16 +# else +# error "LZO_SIZEOF_LONG" +# endif +#endif +#if !defined(LZO_SIZEOF_LONG_LONG) && !defined(LZO_SIZEOF___INT64) +#if (LZO_SIZEOF_LONG > 0 && LZO_SIZEOF_LONG < 8) +# if defined(__LONG_MAX__) && defined(__LONG_LONG_MAX__) +# if (LZO_CC_GNUC >= 0x030300ul) +# if ((__LONG_MAX__)+0 == (__LONG_LONG_MAX__)+0) +# define LZO_SIZEOF_LONG_LONG LZO_SIZEOF_LONG +# elif (__LZO_LSR(__LONG_LONG_MAX__,30) == 1) +# define LZO_SIZEOF_LONG_LONG 4 +# endif +# endif +# endif +#endif +#endif +#if !defined(LZO_SIZEOF_LONG_LONG) && !defined(LZO_SIZEOF___INT64) +#if (LZO_SIZEOF_LONG > 0 && LZO_SIZEOF_LONG < 8) +#if (LZO_ARCH_I086 && LZO_CC_DMC) +#elif (LZO_CC_CILLY) && defined(__GNUC__) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define LZO_SIZEOF_LONG_LONG 8 +#elif ((LZO_OS_WIN32 || LZO_OS_WIN64 || defined(_WIN32)) && LZO_CC_MSC && (_MSC_VER >= 1400)) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_OS_WIN64 || defined(_WIN64)) +# define LZO_SIZEOF___INT64 8 +#elif (LZO_ARCH_I386 && (LZO_CC_DMC)) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_ARCH_I386 && (LZO_CC_SYMANTECC && (__SC__ >= 0x700))) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_ARCH_I386 && (LZO_CC_INTELC && defined(__linux__))) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_ARCH_I386 && (LZO_CC_MWERKS || LZO_CC_PELLESC || LZO_CC_PGI || LZO_CC_SUNPROC)) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_ARCH_I386 && (LZO_CC_INTELC || LZO_CC_MSC)) +# define LZO_SIZEOF___INT64 8 +#elif ((LZO_OS_WIN32 || defined(_WIN32)) && (LZO_CC_MSC)) +# define LZO_SIZEOF___INT64 8 +#elif (LZO_ARCH_I386 && (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0520))) +# define LZO_SIZEOF___INT64 8 +#elif (LZO_ARCH_I386 && (LZO_CC_WATCOMC && (__WATCOMC__ >= 1100))) +# define LZO_SIZEOF___INT64 8 +#elif (LZO_CC_WATCOMC && defined(_INTEGRAL_MAX_BITS) && (_INTEGRAL_MAX_BITS == 64)) +# define LZO_SIZEOF___INT64 8 +#elif (LZO_OS_OS400 || defined(__OS400__)) && defined(__LLP64_IFC__) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (defined(__vms) || defined(__VMS)) && (__INITIAL_POINTER_SIZE+0 == 64) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_CC_SDCC) && (LZO_SIZEOF_INT == 2) +#elif 1 && defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) +# define LZO_SIZEOF_LONG_LONG 8 +#endif +#endif +#endif +#if defined(__cplusplus) && defined(LZO_CC_GNUC) +# if (LZO_CC_GNUC < 0x020800ul) +# undef LZO_SIZEOF_LONG_LONG +# endif +#endif +#if defined(LZO_CFG_NO_LONG_LONG) || defined(__NO_LONG_LONG) +# undef LZO_SIZEOF_LONG_LONG +#endif +#if !defined(LZO_SIZEOF_VOID_P) +#if (LZO_ARCH_I086) +# define __LZO_WORDSIZE 2 +# if (LZO_MM_TINY || LZO_MM_SMALL || LZO_MM_MEDIUM) +# define LZO_SIZEOF_VOID_P 2 +# elif (LZO_MM_COMPACT || LZO_MM_LARGE || LZO_MM_HUGE) +# define LZO_SIZEOF_VOID_P 4 +# else +# error "LZO_MM" +# endif +#elif (LZO_ARCH_AVR || LZO_ARCH_Z80) +# define __LZO_WORDSIZE 1 +# define LZO_SIZEOF_VOID_P 2 +#elif (LZO_ARCH_C166 || LZO_ARCH_MCS51 || LZO_ARCH_MCS251 || LZO_ARCH_MSP430) +# define LZO_SIZEOF_VOID_P 2 +#elif (LZO_ARCH_H8300) +# if defined(__NORMAL_MODE__) +# define __LZO_WORDSIZE 4 +# define LZO_SIZEOF_VOID_P 2 +# elif defined(__H8300H__) || defined(__H8300S__) || defined(__H8300SX__) +# define __LZO_WORDSIZE 4 +# define LZO_SIZEOF_VOID_P 4 +# else +# define __LZO_WORDSIZE 2 +# define LZO_SIZEOF_VOID_P 2 +# endif +# if (LZO_CC_GNUC && (LZO_CC_GNUC < 0x040000ul)) && (LZO_SIZEOF_INT == 4) +# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_INT +# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_INT +# endif +#elif (LZO_ARCH_M16C) +# define __LZO_WORDSIZE 2 +# if defined(__m32c_cpu__) || defined(__m32cm_cpu__) +# define LZO_SIZEOF_VOID_P 4 +# else +# define LZO_SIZEOF_VOID_P 2 +# endif +#elif (LZO_SIZEOF_LONG == 8) && ((defined(__mips__) && defined(__R5900__)) || defined(__MIPS_PSX2__)) +# define __LZO_WORDSIZE 8 +# define LZO_SIZEOF_VOID_P 4 +#elif defined(__LLP64__) || defined(__LLP64) || defined(_LLP64) || defined(_WIN64) +# define __LZO_WORDSIZE 8 +# define LZO_SIZEOF_VOID_P 8 +#elif (LZO_OS_OS400 || defined(__OS400__)) && defined(__LLP64_IFC__) +# define LZO_SIZEOF_VOID_P LZO_SIZEOF_LONG +# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_LONG +# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_LONG +#elif (LZO_OS_OS400 || defined(__OS400__)) +# define __LZO_WORDSIZE LZO_SIZEOF_LONG +# define LZO_SIZEOF_VOID_P 16 +# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_LONG +# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_LONG +#elif (defined(__vms) || defined(__VMS)) && (__INITIAL_POINTER_SIZE+0 == 64) +# define LZO_SIZEOF_VOID_P 8 +# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_LONG +# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_LONG +#elif (LZO_ARCH_SPU) +# if 0 +# define __LZO_WORDSIZE 16 +# endif +# define LZO_SIZEOF_VOID_P 4 +#else +# define LZO_SIZEOF_VOID_P LZO_SIZEOF_LONG +#endif +#endif +#if !defined(LZO_WORDSIZE) +# if defined(__LZO_WORDSIZE) +# define LZO_WORDSIZE __LZO_WORDSIZE +# else +# define LZO_WORDSIZE LZO_SIZEOF_VOID_P +# endif +#endif +#if !defined(LZO_SIZEOF_SIZE_T) +#if (LZO_ARCH_I086 || LZO_ARCH_M16C) +# define LZO_SIZEOF_SIZE_T 2 +#else +# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_VOID_P +#endif +#endif +#if !defined(LZO_SIZEOF_PTRDIFF_T) +#if (LZO_ARCH_I086) +# if (LZO_MM_TINY || LZO_MM_SMALL || LZO_MM_MEDIUM || LZO_MM_HUGE) +# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_VOID_P +# elif (LZO_MM_COMPACT || LZO_MM_LARGE) +# if (LZO_CC_BORLANDC || LZO_CC_TURBOC) +# define LZO_SIZEOF_PTRDIFF_T 4 +# else +# define LZO_SIZEOF_PTRDIFF_T 2 +# endif +# else +# error "LZO_MM" +# endif +#else +# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_SIZE_T +#endif +#endif +#if defined(LZO_ABI_NEUTRAL_ENDIAN) +# undef LZO_ABI_BIG_ENDIAN +# undef LZO_ABI_LITTLE_ENDIAN +#elif !defined(LZO_ABI_BIG_ENDIAN) && !defined(LZO_ABI_LITTLE_ENDIAN) +#if (LZO_ARCH_ALPHA) && (LZO_ARCH_CRAY_MPP) +# define LZO_ABI_BIG_ENDIAN 1 +#elif (LZO_ARCH_ALPHA || LZO_ARCH_AMD64 || LZO_ARCH_BLACKFIN || LZO_ARCH_CRIS || LZO_ARCH_I086 || LZO_ARCH_I386 || LZO_ARCH_MSP430) +# define LZO_ABI_LITTLE_ENDIAN 1 +#elif (LZO_ARCH_M68K || LZO_ARCH_S390) +# define LZO_ABI_BIG_ENDIAN 1 +#elif 1 && defined(__IAR_SYSTEMS_ICC__) && defined(__LITTLE_ENDIAN__) +# if (__LITTLE_ENDIAN__ == 1) +# define LZO_ABI_LITTLE_ENDIAN 1 +# else +# define LZO_ABI_BIG_ENDIAN 1 +# endif +#elif 1 && defined(__BIG_ENDIAN__) && !defined(__LITTLE_ENDIAN__) +# define LZO_ABI_BIG_ENDIAN 1 +#elif 1 && defined(__LITTLE_ENDIAN__) && !defined(__BIG_ENDIAN__) +# define LZO_ABI_LITTLE_ENDIAN 1 +#elif 1 && (LZO_ARCH_ARM) && defined(__ARMEB__) && !defined(__ARMEL__) +# define LZO_ABI_BIG_ENDIAN 1 +#elif 1 && (LZO_ARCH_ARM) && defined(__ARMEL__) && !defined(__ARMEB__) +# define LZO_ABI_LITTLE_ENDIAN 1 +#elif 1 && (LZO_ARCH_MIPS) && defined(__MIPSEB__) && !defined(__MIPSEL__) +# define LZO_ABI_BIG_ENDIAN 1 +#elif 1 && (LZO_ARCH_MIPS) && defined(__MIPSEL__) && !defined(__MIPSEB__) +# define LZO_ABI_LITTLE_ENDIAN 1 +#endif +#endif +#if defined(LZO_ABI_BIG_ENDIAN) && defined(LZO_ABI_LITTLE_ENDIAN) +# error "this should not happen" +#endif +#if defined(LZO_ABI_BIG_ENDIAN) +# define LZO_INFO_ABI_ENDIAN "be" +#elif defined(LZO_ABI_LITTLE_ENDIAN) +# define LZO_INFO_ABI_ENDIAN "le" +#elif defined(LZO_ABI_NEUTRAL_ENDIAN) +# define LZO_INFO_ABI_ENDIAN "neutral" +#endif +#if (LZO_SIZEOF_INT == 1 && LZO_SIZEOF_LONG == 2 && LZO_SIZEOF_VOID_P == 2) +# define LZO_ABI_I8LP16 1 +# define LZO_INFO_ABI_PM "i8lp16" +#elif (LZO_SIZEOF_INT == 2 && LZO_SIZEOF_LONG == 2 && LZO_SIZEOF_VOID_P == 2) +# define LZO_ABI_ILP16 1 +# define LZO_INFO_ABI_PM "ilp16" +#elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 4 && LZO_SIZEOF_VOID_P == 4) +# define LZO_ABI_ILP32 1 +# define LZO_INFO_ABI_PM "ilp32" +#elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 4 && LZO_SIZEOF_VOID_P == 8 && LZO_SIZEOF_SIZE_T == 8) +# define LZO_ABI_LLP64 1 +# define LZO_INFO_ABI_PM "llp64" +#elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 8 && LZO_SIZEOF_VOID_P == 8) +# define LZO_ABI_LP64 1 +# define LZO_INFO_ABI_PM "lp64" +#elif (LZO_SIZEOF_INT == 8 && LZO_SIZEOF_LONG == 8 && LZO_SIZEOF_VOID_P == 8) +# define LZO_ABI_ILP64 1 +# define LZO_INFO_ABI_PM "ilp64" +#elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 8 && LZO_SIZEOF_VOID_P == 4) +# define LZO_ABI_IP32L64 1 +# define LZO_INFO_ABI_PM "ip32l64" +#endif +#if !defined(__LZO_LIBC_OVERRIDE) +#if defined(LZO_LIBC_NAKED) +# define LZO_INFO_LIBC "naked" +#elif defined(LZO_LIBC_FREESTANDING) +# define LZO_INFO_LIBC "freestanding" +#elif defined(LZO_LIBC_MOSTLY_FREESTANDING) +# define LZO_INFO_LIBC "mfreestanding" +#elif defined(LZO_LIBC_ISOC90) +# define LZO_INFO_LIBC "isoc90" +#elif defined(LZO_LIBC_ISOC99) +# define LZO_INFO_LIBC "isoc99" +#elif defined(__dietlibc__) +# define LZO_LIBC_DIETLIBC 1 +# define LZO_INFO_LIBC "dietlibc" +#elif defined(_NEWLIB_VERSION) +# define LZO_LIBC_NEWLIB 1 +# define LZO_INFO_LIBC "newlib" +#elif defined(__UCLIBC__) && defined(__UCLIBC_MAJOR__) && defined(__UCLIBC_MINOR__) +# if defined(__UCLIBC_SUBLEVEL__) +# define LZO_LIBC_UCLIBC (__UCLIBC_MAJOR__ * 0x10000L + __UCLIBC_MINOR__ * 0x100 + __UCLIBC_SUBLEVEL__) +# else +# define LZO_LIBC_UCLIBC 0x00090bL +# endif +# define LZO_INFO_LIBC "uclibc" +#elif defined(__GLIBC__) && defined(__GLIBC_MINOR__) +# define LZO_LIBC_GLIBC (__GLIBC__ * 0x10000L + __GLIBC_MINOR__ * 0x100) +# define LZO_INFO_LIBC "glibc" +#elif (LZO_CC_MWERKS) && defined(__MSL__) +# define LZO_LIBC_MSL __MSL__ +# define LZO_INFO_LIBC "msl" +#elif 1 && defined(__IAR_SYSTEMS_ICC__) +# define LZO_LIBC_ISOC90 1 +# define LZO_INFO_LIBC "isoc90" +#else +# define LZO_LIBC_DEFAULT 1 +# define LZO_INFO_LIBC "default" +#endif +#endif +#if !defined(__lzo_gnuc_extension__) +#if (LZO_CC_GNUC >= 0x020800ul) +# define __lzo_gnuc_extension__ __extension__ +#elif (LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_gnuc_extension__ __extension__ +#else +# define __lzo_gnuc_extension__ +#endif +#endif +#if !defined(__lzo_ua_volatile) +# define __lzo_ua_volatile volatile +#endif +#if !defined(__lzo_alignof) +#if (LZO_CC_CILLY || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI) +# define __lzo_alignof(e) __alignof__(e) +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 700)) +# define __lzo_alignof(e) __alignof__(e) +#elif (LZO_CC_MSC && (_MSC_VER >= 1300)) +# define __lzo_alignof(e) __alignof(e) +#endif +#endif +#if defined(__lzo_alignof) +# define __lzo_HAVE_alignof 1 +#endif +#if !defined(__lzo_constructor) +#if (LZO_CC_GNUC >= 0x030400ul) +# define __lzo_constructor __attribute__((__constructor__,__used__)) +#elif (LZO_CC_GNUC >= 0x020700ul) +# define __lzo_constructor __attribute__((__constructor__)) +#elif (LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_constructor __attribute__((__constructor__)) +#endif +#endif +#if defined(__lzo_constructor) +# define __lzo_HAVE_constructor 1 +#endif +#if !defined(__lzo_destructor) +#if (LZO_CC_GNUC >= 0x030400ul) +# define __lzo_destructor __attribute__((__destructor__,__used__)) +#elif (LZO_CC_GNUC >= 0x020700ul) +# define __lzo_destructor __attribute__((__destructor__)) +#elif (LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_destructor __attribute__((__destructor__)) +#endif +#endif +#if defined(__lzo_destructor) +# define __lzo_HAVE_destructor 1 +#endif +#if defined(__lzo_HAVE_destructor) && !defined(__lzo_HAVE_constructor) +# error "this should not happen" +#endif +#if !defined(__lzo_inline) +#if (LZO_CC_TURBOC && (__TURBOC__ <= 0x0295)) +#elif defined(__cplusplus) +# define __lzo_inline inline +#elif (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0550)) +# define __lzo_inline __inline +#elif (LZO_CC_CILLY || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI) +# define __lzo_inline __inline__ +#elif (LZO_CC_DMC) +# define __lzo_inline __inline +#elif (LZO_CC_INTELC) +# define __lzo_inline __inline +#elif (LZO_CC_MWERKS && (__MWERKS__ >= 0x2405)) +# define __lzo_inline __inline +#elif (LZO_CC_MSC && (_MSC_VER >= 900)) +# define __lzo_inline __inline +#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) +# define __lzo_inline inline +#endif +#endif +#if defined(__lzo_inline) +# define __lzo_HAVE_inline 1 +#else +# define __lzo_inline +#endif +#if !defined(__lzo_forceinline) +#if (LZO_CC_GNUC >= 0x030200ul) +# define __lzo_forceinline __inline__ __attribute__((__always_inline__)) +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 450) && LZO_CC_SYNTAX_MSC) +# define __lzo_forceinline __forceinline +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 800) && LZO_CC_SYNTAX_GNUC) +# define __lzo_forceinline __inline__ __attribute__((__always_inline__)) +#elif (LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_forceinline __inline__ __attribute__((__always_inline__)) +#elif (LZO_CC_MSC && (_MSC_VER >= 1200)) +# define __lzo_forceinline __forceinline +#endif +#endif +#if defined(__lzo_forceinline) +# define __lzo_HAVE_forceinline 1 +#else +# define __lzo_forceinline +#endif +#if !defined(__lzo_noinline) +#if 1 && (LZO_ARCH_I386) && (LZO_CC_GNUC >= 0x040000ul) && (LZO_CC_GNUC < 0x040003ul) +# define __lzo_noinline __attribute__((__noinline__,__used__)) +#elif (LZO_CC_GNUC >= 0x030200ul) +# define __lzo_noinline __attribute__((__noinline__)) +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 600) && LZO_CC_SYNTAX_MSC) +# define __lzo_noinline __declspec(noinline) +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 800) && LZO_CC_SYNTAX_GNUC) +# define __lzo_noinline __attribute__((__noinline__)) +#elif (LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_noinline __attribute__((__noinline__)) +#elif (LZO_CC_MSC && (_MSC_VER >= 1300)) +# define __lzo_noinline __declspec(noinline) +#elif (LZO_CC_MWERKS && (__MWERKS__ >= 0x3200) && (LZO_OS_WIN32 || LZO_OS_WIN64)) +# if defined(__cplusplus) +# else +# define __lzo_noinline __declspec(noinline) +# endif +#endif +#endif +#if defined(__lzo_noinline) +# define __lzo_HAVE_noinline 1 +#else +# define __lzo_noinline +#endif +#if (defined(__lzo_HAVE_forceinline) || defined(__lzo_HAVE_noinline)) && !defined(__lzo_HAVE_inline) +# error "this should not happen" +#endif +#if !defined(__lzo_noreturn) +#if (LZO_CC_GNUC >= 0x020700ul) +# define __lzo_noreturn __attribute__((__noreturn__)) +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 450) && LZO_CC_SYNTAX_MSC) +# define __lzo_noreturn __declspec(noreturn) +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 600) && LZO_CC_SYNTAX_GNUC) +# define __lzo_noreturn __attribute__((__noreturn__)) +#elif (LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_noreturn __attribute__((__noreturn__)) +#elif (LZO_CC_MSC && (_MSC_VER >= 1200)) +# define __lzo_noreturn __declspec(noreturn) +#endif +#endif +#if defined(__lzo_noreturn) +# define __lzo_HAVE_noreturn 1 +#else +# define __lzo_noreturn +#endif +#if !defined(__lzo_nothrow) +#if (LZO_CC_GNUC >= 0x030300ul) +# define __lzo_nothrow __attribute__((__nothrow__)) +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 450) && LZO_CC_SYNTAX_MSC) && defined(__cplusplus) +# define __lzo_nothrow __declspec(nothrow) +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 800) && LZO_CC_SYNTAX_GNUC) +# define __lzo_nothrow __attribute__((__nothrow__)) +#elif (LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_nothrow __attribute__((__nothrow__)) +#elif (LZO_CC_MSC && (_MSC_VER >= 1200)) && defined(__cplusplus) +# define __lzo_nothrow __declspec(nothrow) +#endif +#endif +#if defined(__lzo_nothrow) +# define __lzo_HAVE_nothrow 1 +#else +# define __lzo_nothrow +#endif +#if !defined(__lzo_restrict) +#if (LZO_CC_GNUC >= 0x030400ul) +# define __lzo_restrict __restrict__ +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 600) && LZO_CC_SYNTAX_GNUC) +# define __lzo_restrict __restrict__ +#elif (LZO_CC_LLVM) +# define __lzo_restrict __restrict__ +#elif (LZO_CC_MSC && (_MSC_VER >= 1400)) +# define __lzo_restrict __restrict +#endif +#endif +#if defined(__lzo_restrict) +# define __lzo_HAVE_restrict 1 +#else +# define __lzo_restrict +#endif +#if !defined(__lzo_likely) && !defined(__lzo_unlikely) +#if (LZO_CC_GNUC >= 0x030200ul) +# define __lzo_likely(e) (__builtin_expect(!!(e),1)) +# define __lzo_unlikely(e) (__builtin_expect(!!(e),0)) +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 800)) +# define __lzo_likely(e) (__builtin_expect(!!(e),1)) +# define __lzo_unlikely(e) (__builtin_expect(!!(e),0)) +#elif (LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_likely(e) (__builtin_expect(!!(e),1)) +# define __lzo_unlikely(e) (__builtin_expect(!!(e),0)) +#endif +#endif +#if defined(__lzo_likely) +# define __lzo_HAVE_likely 1 +#else +# define __lzo_likely(e) (e) +#endif +#if defined(__lzo_unlikely) +# define __lzo_HAVE_unlikely 1 +#else +# define __lzo_unlikely(e) (e) +#endif +#if !defined(LZO_UNUSED) +# if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0600)) +# define LZO_UNUSED(var) ((void) &var) +# elif (LZO_CC_BORLANDC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PELLESC || LZO_CC_TURBOC) +# define LZO_UNUSED(var) if (&var) ; else +# elif (LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define LZO_UNUSED(var) ((void) var) +# elif (LZO_CC_MSC && (_MSC_VER < 900)) +# define LZO_UNUSED(var) if (&var) ; else +# elif (LZO_CC_KEILC) +# define LZO_UNUSED(var) {extern int __lzo_unused[1-2*!(sizeof(var)>0)];} +# elif (LZO_CC_PACIFICC) +# define LZO_UNUSED(var) ((void) sizeof(var)) +# elif (LZO_CC_WATCOMC) && defined(__cplusplus) +# define LZO_UNUSED(var) ((void) var) +# else +# define LZO_UNUSED(var) ((void) &var) +# endif +#endif +#if !defined(LZO_UNUSED_FUNC) +# if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0600)) +# define LZO_UNUSED_FUNC(func) ((void) func) +# elif (LZO_CC_BORLANDC || LZO_CC_NDPC || LZO_CC_TURBOC) +# define LZO_UNUSED_FUNC(func) if (func) ; else +# elif (LZO_CC_LLVM) +# define LZO_UNUSED_FUNC(func) ((void) &func) +# elif (LZO_CC_MSC && (_MSC_VER < 900)) +# define LZO_UNUSED_FUNC(func) if (func) ; else +# elif (LZO_CC_MSC) +# define LZO_UNUSED_FUNC(func) ((void) &func) +# elif (LZO_CC_KEILC || LZO_CC_PELLESC) +# define LZO_UNUSED_FUNC(func) {extern int __lzo_unused[1-2*!(sizeof((int)func)>0)];} +# else +# define LZO_UNUSED_FUNC(func) ((void) func) +# endif +#endif +#if !defined(LZO_UNUSED_LABEL) +# if (LZO_CC_WATCOMC) && defined(__cplusplus) +# define LZO_UNUSED_LABEL(l) switch(0) case 1:goto l +# elif (LZO_CC_INTELC || LZO_CC_WATCOMC) +# define LZO_UNUSED_LABEL(l) if (0) goto l +# else +# define LZO_UNUSED_LABEL(l) switch(0) case 1:goto l +# endif +#endif +#if !defined(LZO_DEFINE_UNINITIALIZED_VAR) +# if 0 +# define LZO_DEFINE_UNINITIALIZED_VAR(type,var,init) type var +# elif 0 && (LZO_CC_GNUC) +# define LZO_DEFINE_UNINITIALIZED_VAR(type,var,init) type var = var +# else +# define LZO_DEFINE_UNINITIALIZED_VAR(type,var,init) type var = init +# endif +#endif +#if !defined(LZO_COMPILE_TIME_ASSERT_HEADER) +# if (LZO_CC_AZTECC || LZO_CC_ZORTECHC) +# define LZO_COMPILE_TIME_ASSERT_HEADER(e) extern int __lzo_cta[1-!(e)]; +# elif (LZO_CC_DMC || LZO_CC_SYMANTECC) +# define LZO_COMPILE_TIME_ASSERT_HEADER(e) extern int __lzo_cta[1u-2*!(e)]; +# elif (LZO_CC_TURBOC && (__TURBOC__ == 0x0295)) +# define LZO_COMPILE_TIME_ASSERT_HEADER(e) extern int __lzo_cta[1-!(e)]; +# else +# define LZO_COMPILE_TIME_ASSERT_HEADER(e) extern int __lzo_cta[1-2*!(e)]; +# endif +#endif +#if !defined(LZO_COMPILE_TIME_ASSERT) +# if (LZO_CC_AZTECC) +# define LZO_COMPILE_TIME_ASSERT(e) {typedef int __lzo_cta_t[1-!(e)];} +# elif (LZO_CC_DMC || LZO_CC_PACIFICC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC) +# define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break; +# elif (LZO_CC_MSC && (_MSC_VER < 900)) +# define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break; +# elif (LZO_CC_TURBOC && (__TURBOC__ == 0x0295)) +# define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break; +# else +# define LZO_COMPILE_TIME_ASSERT(e) {typedef int __lzo_cta_t[1-2*!(e)];} +# endif +#endif +#if (LZO_ARCH_I086 || LZO_ARCH_I386) && (LZO_OS_DOS16 || LZO_OS_DOS32 || LZO_OS_OS2 || LZO_OS_OS216 || LZO_OS_WIN16 || LZO_OS_WIN32 || LZO_OS_WIN64) +# if (LZO_CC_GNUC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PACIFICC) +# elif (LZO_CC_DMC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC) +# define __lzo_cdecl __cdecl +# define __lzo_cdecl_atexit +# define __lzo_cdecl_main __cdecl +# if (LZO_OS_OS2 && (LZO_CC_DMC || LZO_CC_SYMANTECC)) +# define __lzo_cdecl_qsort __pascal +# elif (LZO_OS_OS2 && (LZO_CC_ZORTECHC)) +# define __lzo_cdecl_qsort _stdcall +# else +# define __lzo_cdecl_qsort __cdecl +# endif +# elif (LZO_CC_WATCOMC) +# define __lzo_cdecl __cdecl +# else +# define __lzo_cdecl __cdecl +# define __lzo_cdecl_atexit __cdecl +# define __lzo_cdecl_main __cdecl +# define __lzo_cdecl_qsort __cdecl +# endif +# if (LZO_CC_GNUC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PACIFICC || LZO_CC_WATCOMC) +# elif (LZO_OS_OS2 && (LZO_CC_DMC || LZO_CC_SYMANTECC)) +# define __lzo_cdecl_sighandler __pascal +# elif (LZO_OS_OS2 && (LZO_CC_ZORTECHC)) +# define __lzo_cdecl_sighandler _stdcall +# elif (LZO_CC_MSC && (_MSC_VER >= 1400)) && defined(_M_CEE_PURE) +# define __lzo_cdecl_sighandler __clrcall +# elif (LZO_CC_MSC && (_MSC_VER >= 600 && _MSC_VER < 700)) +# if defined(_DLL) +# define __lzo_cdecl_sighandler _far _cdecl _loadds +# elif defined(_MT) +# define __lzo_cdecl_sighandler _far _cdecl +# else +# define __lzo_cdecl_sighandler _cdecl +# endif +# else +# define __lzo_cdecl_sighandler __cdecl +# endif +#elif (LZO_ARCH_I386) && (LZO_CC_WATCOMC) +# define __lzo_cdecl __cdecl +#elif (LZO_ARCH_M68K && LZO_OS_TOS && (LZO_CC_PUREC || LZO_CC_TURBOC)) +# define __lzo_cdecl cdecl +#endif +#if !defined(__lzo_cdecl) +# define __lzo_cdecl +#endif +#if !defined(__lzo_cdecl_atexit) +# define __lzo_cdecl_atexit +#endif +#if !defined(__lzo_cdecl_main) +# define __lzo_cdecl_main +#endif +#if !defined(__lzo_cdecl_qsort) +# define __lzo_cdecl_qsort +#endif +#if !defined(__lzo_cdecl_sighandler) +# define __lzo_cdecl_sighandler +#endif +#if !defined(__lzo_cdecl_va) +# define __lzo_cdecl_va __lzo_cdecl +#endif +#if !defined(LZO_CFG_NO_WINDOWS_H) +#if (LZO_OS_CYGWIN || (LZO_OS_EMX && defined(__RSXNT__)) || LZO_OS_WIN32 || LZO_OS_WIN64) +# if (LZO_CC_WATCOMC && (__WATCOMC__ < 1000)) +# elif (LZO_OS_WIN32 && LZO_CC_GNUC) && defined(__PW32__) +# elif ((LZO_OS_CYGWIN || defined(__MINGW32__)) && (LZO_CC_GNUC && (LZO_CC_GNUC < 0x025f00ul))) +# else +# define LZO_HAVE_WINDOWS_H 1 +# endif +#endif +#endif +#if (LZO_ARCH_ALPHA) +# define LZO_OPT_AVOID_UINT_INDEX 1 +# define LZO_OPT_AVOID_SHORT 1 +# define LZO_OPT_AVOID_USHORT 1 +#elif (LZO_ARCH_AMD64) +# define LZO_OPT_AVOID_INT_INDEX 1 +# define LZO_OPT_AVOID_UINT_INDEX 1 +# define LZO_OPT_UNALIGNED16 1 +# define LZO_OPT_UNALIGNED32 1 +# define LZO_OPT_UNALIGNED64 1 +#elif (LZO_ARCH_ARM && LZO_ARCH_ARM_THUMB) +#elif (LZO_ARCH_ARM) +# define LZO_OPT_AVOID_SHORT 1 +# define LZO_OPT_AVOID_USHORT 1 +#elif (LZO_ARCH_CRIS) +# define LZO_OPT_UNALIGNED16 1 +# define LZO_OPT_UNALIGNED32 1 +#elif (LZO_ARCH_I386) +# define LZO_OPT_UNALIGNED16 1 +# define LZO_OPT_UNALIGNED32 1 +#elif (LZO_ARCH_IA64) +# define LZO_OPT_AVOID_INT_INDEX 1 +# define LZO_OPT_AVOID_UINT_INDEX 1 +# define LZO_OPT_PREFER_POSTINC 1 +#elif (LZO_ARCH_M68K) +# define LZO_OPT_PREFER_POSTINC 1 +# define LZO_OPT_PREFER_PREDEC 1 +# if defined(__mc68020__) && !defined(__mcoldfire__) +# define LZO_OPT_UNALIGNED16 1 +# define LZO_OPT_UNALIGNED32 1 +# endif +#elif (LZO_ARCH_MIPS) +# define LZO_OPT_AVOID_UINT_INDEX 1 +#elif (LZO_ARCH_POWERPC) +# define LZO_OPT_PREFER_PREINC 1 +# define LZO_OPT_PREFER_PREDEC 1 +# if defined(LZO_ABI_BIG_ENDIAN) +# define LZO_OPT_UNALIGNED16 1 +# define LZO_OPT_UNALIGNED32 1 +# endif +#elif (LZO_ARCH_S390) +# define LZO_OPT_UNALIGNED16 1 +# define LZO_OPT_UNALIGNED32 1 +# if (LZO_SIZEOF_SIZE_T == 8) +# define LZO_OPT_UNALIGNED64 1 +# endif +#elif (LZO_ARCH_SH) +# define LZO_OPT_PREFER_POSTINC 1 +# define LZO_OPT_PREFER_PREDEC 1 +#endif +#if !defined(LZO_CFG_NO_INLINE_ASM) +#if defined(LZO_CC_LLVM) +# define LZO_CFG_NO_INLINE_ASM 1 +#endif +#endif +#if !defined(LZO_CFG_NO_UNALIGNED) +#if defined(LZO_ABI_NEUTRAL_ENDIAN) || defined(LZO_ARCH_GENERIC) +# define LZO_CFG_NO_UNALIGNED 1 +#endif +#endif +#if defined(LZO_CFG_NO_UNALIGNED) +# undef LZO_OPT_UNALIGNED16 +# undef LZO_OPT_UNALIGNED32 +# undef LZO_OPT_UNALIGNED64 +#endif +#if defined(LZO_CFG_NO_INLINE_ASM) +#elif (LZO_ARCH_I386 && (LZO_OS_DOS32 || LZO_OS_WIN32) && (LZO_CC_DMC || LZO_CC_INTELC || LZO_CC_MSC || LZO_CC_PELLESC)) +# define LZO_ASM_SYNTAX_MSC 1 +#elif (LZO_OS_WIN64 && (LZO_CC_DMC || LZO_CC_INTELC || LZO_CC_MSC || LZO_CC_PELLESC)) +#elif (LZO_ARCH_I386 && (LZO_CC_GNUC || LZO_CC_INTELC || LZO_CC_PATHSCALE)) +# define LZO_ASM_SYNTAX_GNUC 1 +#elif (LZO_ARCH_AMD64 && (LZO_CC_GNUC || LZO_CC_INTELC || LZO_CC_PATHSCALE)) +# define LZO_ASM_SYNTAX_GNUC 1 +#endif +#if (LZO_ASM_SYNTAX_GNUC) +#if (LZO_ARCH_I386 && LZO_CC_GNUC && (LZO_CC_GNUC < 0x020000ul)) +# define __LZO_ASM_CLOBBER "ax" +#elif (LZO_CC_INTELC) +# define __LZO_ASM_CLOBBER "memory" +#else +# define __LZO_ASM_CLOBBER "cc", "memory" +#endif +#endif +#if defined(__LZO_INFOSTR_MM) +#elif (LZO_MM_FLAT) && (defined(__LZO_INFOSTR_PM) || defined(LZO_INFO_ABI_PM)) +# define __LZO_INFOSTR_MM "" +#elif defined(LZO_INFO_MM) +# define __LZO_INFOSTR_MM "." LZO_INFO_MM +#else +# define __LZO_INFOSTR_MM "" +#endif +#if defined(__LZO_INFOSTR_PM) +#elif defined(LZO_INFO_ABI_PM) +# define __LZO_INFOSTR_PM "." LZO_INFO_ABI_PM +#else +# define __LZO_INFOSTR_PM "" +#endif +#if defined(__LZO_INFOSTR_ENDIAN) +#elif defined(LZO_INFO_ABI_ENDIAN) +# define __LZO_INFOSTR_ENDIAN "." LZO_INFO_ABI_ENDIAN +#else +# define __LZO_INFOSTR_ENDIAN "" +#endif +#if defined(__LZO_INFOSTR_OSNAME) +#elif defined(LZO_INFO_OS_CONSOLE) +# define __LZO_INFOSTR_OSNAME LZO_INFO_OS "." LZO_INFO_OS_CONSOLE +#elif defined(LZO_INFO_OS_POSIX) +# define __LZO_INFOSTR_OSNAME LZO_INFO_OS "." LZO_INFO_OS_POSIX +#else +# define __LZO_INFOSTR_OSNAME LZO_INFO_OS +#endif +#if defined(__LZO_INFOSTR_LIBC) +#elif defined(LZO_INFO_LIBC) +# define __LZO_INFOSTR_LIBC "." LZO_INFO_LIBC +#else +# define __LZO_INFOSTR_LIBC "" +#endif +#if defined(__LZO_INFOSTR_CCVER) +#elif defined(LZO_INFO_CCVER) +# define __LZO_INFOSTR_CCVER " " LZO_INFO_CCVER +#else +# define __LZO_INFOSTR_CCVER "" +#endif +#define LZO_INFO_STRING \ + LZO_INFO_ARCH __LZO_INFOSTR_MM __LZO_INFOSTR_PM __LZO_INFOSTR_ENDIAN \ + " " __LZO_INFOSTR_OSNAME __LZO_INFOSTR_LIBC " " LZO_INFO_CC __LZO_INFOSTR_CCVER + +#endif + +#endif + +#undef LZO_HAVE_CONFIG_H +#include "minilzo.h" + +#if !defined(MINILZO_VERSION) || (MINILZO_VERSION != 0x2030) +# error "version mismatch in miniLZO source files" +#endif + +#ifdef MINILZO_HAVE_CONFIG_H +# define LZO_HAVE_CONFIG_H +#endif + +#ifndef __LZO_CONF_H +#define __LZO_CONF_H + +#if !defined(__LZO_IN_MINILZO) +#if defined(LZO_CFG_FREESTANDING) +# define LZO_LIBC_FREESTANDING 1 +# define LZO_OS_FREESTANDING 1 +# define ACC_LIBC_FREESTANDING 1 +# define ACC_OS_FREESTANDING 1 +#endif +#if defined(LZO_CFG_NO_UNALIGNED) +# define ACC_CFG_NO_UNALIGNED 1 +#endif +#if defined(LZO_ARCH_GENERIC) +# define ACC_ARCH_GENERIC 1 +#endif +#if defined(LZO_ABI_NEUTRAL_ENDIAN) +# define ACC_ABI_NEUTRAL_ENDIAN 1 +#endif +#if defined(LZO_HAVE_CONFIG_H) +# define ACC_CONFIG_NO_HEADER 1 +#endif +#if defined(LZO_CFG_EXTRA_CONFIG_HEADER) +# include LZO_CFG_EXTRA_CONFIG_HEADER +#endif +#if defined(__LZOCONF_H) || defined(__LZOCONF_H_INCLUDED) +# error "include this file first" +#endif +#include "lzo/lzoconf.h" +#endif + +#if (LZO_VERSION < 0x02000) || !defined(__LZOCONF_H_INCLUDED) +# error "version mismatch" +#endif + +#if (LZO_CC_BORLANDC && LZO_ARCH_I086) +# pragma option -h +#endif + +#if (LZO_CC_MSC && (_MSC_VER >= 1000)) +# pragma warning(disable: 4127 4701) +#endif +#if (LZO_CC_MSC && (_MSC_VER >= 1300)) +# pragma warning(disable: 4820) +# pragma warning(disable: 4514 4710 4711) +#endif + +#if (LZO_CC_SUNPROC) +# pragma error_messages(off,E_END_OF_LOOP_CODE_NOT_REACHED) +# pragma error_messages(off,E_LOOP_NOT_ENTERED_AT_TOP) +#endif + +#if defined(__LZO_MMODEL_HUGE) && (!LZO_HAVE_MM_HUGE_PTR) +# error "this should not happen - check defines for __huge" +#endif + +#if defined(__LZO_IN_MINILZO) || defined(LZO_CFG_FREESTANDING) +#elif (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16) +# define ACC_WANT_ACC_INCD_H 1 +# define ACC_WANT_ACC_INCE_H 1 +# define ACC_WANT_ACC_INCI_H 1 +#elif 1 +# include +#else +# define ACC_WANT_ACC_INCD_H 1 +#endif + +#if (LZO_ARCH_I086) +# define ACC_MM_AHSHIFT LZO_MM_AHSHIFT +# define ACC_PTR_FP_OFF(x) (((const unsigned __far*)&(x))[0]) +# define ACC_PTR_FP_SEG(x) (((const unsigned __far*)&(x))[1]) +# define ACC_PTR_MK_FP(s,o) ((void __far*)(((unsigned long)(s)<<16)+(unsigned)(o))) +#endif + +#if !defined(lzo_uintptr_t) +# if defined(__LZO_MMODEL_HUGE) +# define lzo_uintptr_t unsigned long +# elif 1 && defined(LZO_OS_OS400) && (LZO_SIZEOF_VOID_P == 16) +# define __LZO_UINTPTR_T_IS_POINTER 1 + typedef char* lzo_uintptr_t; +# define lzo_uintptr_t lzo_uintptr_t +# elif (LZO_SIZEOF_SIZE_T == LZO_SIZEOF_VOID_P) +# define lzo_uintptr_t size_t +# elif (LZO_SIZEOF_LONG == LZO_SIZEOF_VOID_P) +# define lzo_uintptr_t unsigned long +# elif (LZO_SIZEOF_INT == LZO_SIZEOF_VOID_P) +# define lzo_uintptr_t unsigned int +# elif (LZO_SIZEOF_LONG_LONG == LZO_SIZEOF_VOID_P) +# define lzo_uintptr_t unsigned long long +# else +# define lzo_uintptr_t size_t +# endif +#endif +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uintptr_t) >= sizeof(lzo_voidp)) + +#if 1 && !defined(LZO_CFG_FREESTANDING) +#if 1 && !defined(HAVE_STRING_H) +#define HAVE_STRING_H 1 +#endif +#if 1 && !defined(HAVE_MEMCMP) +#define HAVE_MEMCMP 1 +#endif +#if 1 && !defined(HAVE_MEMCPY) +#define HAVE_MEMCPY 1 +#endif +#if 1 && !defined(HAVE_MEMMOVE) +#define HAVE_MEMMOVE 1 +#endif +#if 1 && !defined(HAVE_MEMSET) +#define HAVE_MEMSET 1 +#endif +#endif + +#if 1 && defined(HAVE_STRING_H) +#include +#endif + +#if defined(LZO_CFG_FREESTANDING) +# undef HAVE_MEMCMP +# undef HAVE_MEMCPY +# undef HAVE_MEMMOVE +# undef HAVE_MEMSET +#endif + +#if !defined(HAVE_MEMCMP) +# undef memcmp +# define memcmp(a,b,c) lzo_memcmp(a,b,c) +#elif !defined(__LZO_MMODEL_HUGE) +# define lzo_memcmp(a,b,c) memcmp(a,b,c) +#endif +#if !defined(HAVE_MEMCPY) +# undef memcpy +# define memcpy(a,b,c) lzo_memcpy(a,b,c) +#elif !defined(__LZO_MMODEL_HUGE) +# define lzo_memcpy(a,b,c) memcpy(a,b,c) +#endif +#if !defined(HAVE_MEMMOVE) +# undef memmove +# define memmove(a,b,c) lzo_memmove(a,b,c) +#elif !defined(__LZO_MMODEL_HUGE) +# define lzo_memmove(a,b,c) memmove(a,b,c) +#endif +#if !defined(HAVE_MEMSET) +# undef memset +# define memset(a,b,c) lzo_memset(a,b,c) +#elif !defined(__LZO_MMODEL_HUGE) +# define lzo_memset(a,b,c) memset(a,b,c) +#endif + +#undef NDEBUG +#if defined(LZO_CFG_FREESTANDING) +# undef LZO_DEBUG +# define NDEBUG 1 +# undef assert +# define assert(e) ((void)0) +#else +# if !defined(LZO_DEBUG) +# define NDEBUG 1 +# endif +# include +#endif + +#if 0 && defined(__BOUNDS_CHECKING_ON) +# include +#else +# define BOUNDS_CHECKING_OFF_DURING(stmt) stmt +# define BOUNDS_CHECKING_OFF_IN_EXPR(expr) (expr) +#endif + +#if !defined(__lzo_inline) +# define __lzo_inline +#endif +#if !defined(__lzo_forceinline) +# define __lzo_forceinline +#endif +#if !defined(__lzo_noinline) +# define __lzo_noinline +#endif + +#if 1 +# define LZO_BYTE(x) ((unsigned char) (x)) +#else +# define LZO_BYTE(x) ((unsigned char) ((x) & 0xff)) +#endif + +#define LZO_MAX(a,b) ((a) >= (b) ? (a) : (b)) +#define LZO_MIN(a,b) ((a) <= (b) ? (a) : (b)) +#define LZO_MAX3(a,b,c) ((a) >= (b) ? LZO_MAX(a,c) : LZO_MAX(b,c)) +#define LZO_MIN3(a,b,c) ((a) <= (b) ? LZO_MIN(a,c) : LZO_MIN(b,c)) + +#define lzo_sizeof(type) ((lzo_uint) (sizeof(type))) + +#define LZO_HIGH(array) ((lzo_uint) (sizeof(array)/sizeof(*(array)))) + +#define LZO_SIZE(bits) (1u << (bits)) +#define LZO_MASK(bits) (LZO_SIZE(bits) - 1) + +#define LZO_LSIZE(bits) (1ul << (bits)) +#define LZO_LMASK(bits) (LZO_LSIZE(bits) - 1) + +#define LZO_USIZE(bits) ((lzo_uint) 1 << (bits)) +#define LZO_UMASK(bits) (LZO_USIZE(bits) - 1) + +#if !defined(DMUL) +#if 0 + +# define DMUL(a,b) ((lzo_xint) ((lzo_uint32)(a) * (lzo_uint32)(b))) +#else +# define DMUL(a,b) ((lzo_xint) ((a) * (b))) +#endif +#endif + +#if 1 && !defined(LZO_CFG_NO_UNALIGNED) +#if 1 && (LZO_ARCH_AMD64 || LZO_ARCH_I386) +# if (LZO_SIZEOF_SHORT == 2) +# define LZO_UNALIGNED_OK_2 +# endif +# if (LZO_SIZEOF_INT == 4) +# define LZO_UNALIGNED_OK_4 +# endif +#endif +#endif + +#if defined(LZO_UNALIGNED_OK_2) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(short) == 2) +#endif +#if defined(LZO_UNALIGNED_OK_4) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint32) == 4) +#elif defined(LZO_ALIGNED_OK_4) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint32) == 4) +#endif + +#define MEMCPY8_DS(dest,src,len) \ + lzo_memcpy(dest,src,len); dest += len; src += len + +#define BZERO8_PTR(s,l,n) \ + lzo_memset((lzo_voidp)(s),0,(lzo_uint)(l)*(n)) + +#define MEMCPY_DS(dest,src,len) \ + do *dest++ = *src++; while (--len > 0) + +__LZO_EXTERN_C int __lzo_init_done; +__LZO_EXTERN_C const char __lzo_copyright[]; +LZO_EXTERN(const lzo_bytep) lzo_copyright(void); + +#ifndef __LZO_PTR_H +#define __LZO_PTR_H + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(lzo_uintptr_t) +# if defined(__LZO_MMODEL_HUGE) +# define lzo_uintptr_t unsigned long +# else +# define lzo_uintptr_t acc_uintptr_t +# ifdef __ACC_INTPTR_T_IS_POINTER +# define __LZO_UINTPTR_T_IS_POINTER 1 +# endif +# endif +#endif + +#if (LZO_ARCH_I086) +#define PTR(a) ((lzo_bytep) (a)) +#define PTR_ALIGNED_4(a) ((ACC_PTR_FP_OFF(a) & 3) == 0) +#define PTR_ALIGNED2_4(a,b) (((ACC_PTR_FP_OFF(a) | ACC_PTR_FP_OFF(b)) & 3) == 0) +#elif (LZO_MM_PVP) +#define PTR(a) ((lzo_bytep) (a)) +#define PTR_ALIGNED_8(a) ((((lzo_uintptr_t)(a)) >> 61) == 0) +#define PTR_ALIGNED2_8(a,b) ((((lzo_uintptr_t)(a)|(lzo_uintptr_t)(b)) >> 61) == 0) +#else +#define PTR(a) ((lzo_uintptr_t) (a)) +#define PTR_LINEAR(a) PTR(a) +#define PTR_ALIGNED_4(a) ((PTR_LINEAR(a) & 3) == 0) +#define PTR_ALIGNED_8(a) ((PTR_LINEAR(a) & 7) == 0) +#define PTR_ALIGNED2_4(a,b) (((PTR_LINEAR(a) | PTR_LINEAR(b)) & 3) == 0) +#define PTR_ALIGNED2_8(a,b) (((PTR_LINEAR(a) | PTR_LINEAR(b)) & 7) == 0) +#endif + +#define PTR_LT(a,b) (PTR(a) < PTR(b)) +#define PTR_GE(a,b) (PTR(a) >= PTR(b)) +#define PTR_DIFF(a,b) (PTR(a) - PTR(b)) +#define pd(a,b) ((lzo_uint) ((a)-(b))) + +LZO_EXTERN(lzo_uintptr_t) +__lzo_ptr_linear(const lzo_voidp ptr); + +typedef union +{ + char a_char; + unsigned char a_uchar; + short a_short; + unsigned short a_ushort; + int a_int; + unsigned int a_uint; + long a_long; + unsigned long a_ulong; + lzo_int a_lzo_int; + lzo_uint a_lzo_uint; + lzo_int32 a_lzo_int32; + lzo_uint32 a_lzo_uint32; + ptrdiff_t a_ptrdiff_t; + lzo_uintptr_t a_lzo_uintptr_t; + lzo_voidp a_lzo_voidp; + void * a_void_p; + lzo_bytep a_lzo_bytep; + lzo_bytepp a_lzo_bytepp; + lzo_uintp a_lzo_uintp; + lzo_uint * a_lzo_uint_p; + lzo_uint32p a_lzo_uint32p; + lzo_uint32 * a_lzo_uint32_p; + unsigned char * a_uchar_p; + char * a_char_p; +} +lzo_full_align_t; + +#ifdef __cplusplus +} +#endif + +#endif + +#define LZO_DETERMINISTIC + +#define LZO_DICT_USE_PTR +#if 0 && (LZO_ARCH_I086) +# undef LZO_DICT_USE_PTR +#endif + +#if defined(LZO_DICT_USE_PTR) +# define lzo_dict_t const lzo_bytep +# define lzo_dict_p lzo_dict_t __LZO_MMODEL * +#else +# define lzo_dict_t lzo_uint +# define lzo_dict_p lzo_dict_t __LZO_MMODEL * +#endif + +#endif + +#if !defined(MINILZO_CFG_SKIP_LZO_PTR) + +LZO_PUBLIC(lzo_uintptr_t) +__lzo_ptr_linear(const lzo_voidp ptr) +{ + lzo_uintptr_t p; + +#if (LZO_ARCH_I086) + p = (((lzo_uintptr_t)(ACC_PTR_FP_SEG(ptr))) << (16 - ACC_MM_AHSHIFT)) + (ACC_PTR_FP_OFF(ptr)); +#elif (LZO_MM_PVP) + p = (lzo_uintptr_t) (ptr); + p = (p << 3) | (p >> 61); +#else + p = (lzo_uintptr_t) PTR_LINEAR(ptr); +#endif + + return p; +} + +LZO_PUBLIC(unsigned) +__lzo_align_gap(const lzo_voidp ptr, lzo_uint size) +{ +#if defined(__LZO_UINTPTR_T_IS_POINTER) + size_t n = (size_t) ptr; + n = (((n + size - 1) / size) * size) - n; +#else + lzo_uintptr_t p, n; + p = __lzo_ptr_linear(ptr); + n = (((p + size - 1) / size) * size) - p; +#endif + + assert(size > 0); + assert((long)n >= 0); + assert(n <= size); + return (unsigned)n; +} + +#endif + +/* If you use the LZO library in a product, I would appreciate that you + * keep this copyright string in the executable of your product. + */ + +const char __lzo_copyright[] = +#if !defined(__LZO_IN_MINLZO) + LZO_VERSION_STRING; +#else + "\r\n\n" + "LZO data compression library.\n" + "$Copyright: LZO (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 Markus Franz Xaver Johannes Oberhumer\n" + "\n" + "http://www.oberhumer.com $\n\n" + "$Id: LZO version: v" LZO_VERSION_STRING ", " LZO_VERSION_DATE " $\n" + "$Built: " __DATE__ " " __TIME__ " $\n" + "$Info: " LZO_INFO_STRING " $\n"; +#endif + +LZO_PUBLIC(const lzo_bytep) +lzo_copyright(void) +{ +#if (LZO_OS_DOS16 && LZO_CC_TURBOC) + return (lzo_voidp) __lzo_copyright; +#else + return (const lzo_bytep) __lzo_copyright; +#endif +} + +LZO_PUBLIC(unsigned) +lzo_version(void) +{ + return LZO_VERSION; +} + +LZO_PUBLIC(const char *) +lzo_version_string(void) +{ + return LZO_VERSION_STRING; +} + +LZO_PUBLIC(const char *) +lzo_version_date(void) +{ + return LZO_VERSION_DATE; +} + +LZO_PUBLIC(const lzo_charp) +_lzo_version_string(void) +{ + return LZO_VERSION_STRING; +} + +LZO_PUBLIC(const lzo_charp) +_lzo_version_date(void) +{ + return LZO_VERSION_DATE; +} + +#define LZO_BASE 65521u +#define LZO_NMAX 5552 + +#define LZO_DO1(buf,i) s1 += buf[i]; s2 += s1 +#define LZO_DO2(buf,i) LZO_DO1(buf,i); LZO_DO1(buf,i+1); +#define LZO_DO4(buf,i) LZO_DO2(buf,i); LZO_DO2(buf,i+2); +#define LZO_DO8(buf,i) LZO_DO4(buf,i); LZO_DO4(buf,i+4); +#define LZO_DO16(buf,i) LZO_DO8(buf,i); LZO_DO8(buf,i+8); + +LZO_PUBLIC(lzo_uint32) +lzo_adler32(lzo_uint32 adler, const lzo_bytep buf, lzo_uint len) +{ + lzo_uint32 s1 = adler & 0xffff; + lzo_uint32 s2 = (adler >> 16) & 0xffff; + unsigned k; + + if (buf == NULL) + return 1; + + while (len > 0) + { + k = len < LZO_NMAX ? (unsigned) len : LZO_NMAX; + len -= k; + if (k >= 16) do + { + LZO_DO16(buf,0); + buf += 16; + k -= 16; + } while (k >= 16); + if (k != 0) do + { + s1 += *buf++; + s2 += s1; + } while (--k > 0); + s1 %= LZO_BASE; + s2 %= LZO_BASE; + } + return (s2 << 16) | s1; +} + +#undef LZO_DO1 +#undef LZO_DO2 +#undef LZO_DO4 +#undef LZO_DO8 +#undef LZO_DO16 + +#if !defined(MINILZO_CFG_SKIP_LZO_STRING) +#undef lzo_memcmp +#undef lzo_memcpy +#undef lzo_memmove +#undef lzo_memset +#if !defined(__LZO_MMODEL_HUGE) +# undef LZO_HAVE_MM_HUGE_PTR +#endif +#define lzo_hsize_t lzo_uint +#define lzo_hvoid_p lzo_voidp +#define lzo_hbyte_p lzo_bytep +#define LZOLIB_PUBLIC(r,f) LZO_PUBLIC(r) f +#define lzo_hmemcmp lzo_memcmp +#define lzo_hmemcpy lzo_memcpy +#define lzo_hmemmove lzo_memmove +#define lzo_hmemset lzo_memset +#define __LZOLIB_HMEMCPY_CH_INCLUDED 1 +#if !defined(LZOLIB_PUBLIC) +# define LZOLIB_PUBLIC(r,f) r __LZOLIB_FUNCNAME(f) +#endif +LZOLIB_PUBLIC(int, lzo_hmemcmp) (const lzo_hvoid_p s1, const lzo_hvoid_p s2, lzo_hsize_t len) +{ +#if (LZO_HAVE_MM_HUGE_PTR) || !defined(HAVE_MEMCMP) + const lzo_hbyte_p p1 = (const lzo_hbyte_p) s1; + const lzo_hbyte_p p2 = (const lzo_hbyte_p) s2; + if __lzo_likely(len > 0) do + { + int d = *p1 - *p2; + if (d != 0) + return d; + p1++; p2++; + } while __lzo_likely(--len > 0); + return 0; +#else + return memcmp(s1, s2, len); +#endif +} +LZOLIB_PUBLIC(lzo_hvoid_p, lzo_hmemcpy) (lzo_hvoid_p dest, const lzo_hvoid_p src, lzo_hsize_t len) +{ +#if (LZO_HAVE_MM_HUGE_PTR) || !defined(HAVE_MEMCPY) + lzo_hbyte_p p1 = (lzo_hbyte_p) dest; + const lzo_hbyte_p p2 = (const lzo_hbyte_p) src; + if (!(len > 0) || p1 == p2) + return dest; + do + *p1++ = *p2++; + while __lzo_likely(--len > 0); + return dest; +#else + return memcpy(dest, src, len); +#endif +} +LZOLIB_PUBLIC(lzo_hvoid_p, lzo_hmemmove) (lzo_hvoid_p dest, const lzo_hvoid_p src, lzo_hsize_t len) +{ +#if (LZO_HAVE_MM_HUGE_PTR) || !defined(HAVE_MEMMOVE) + lzo_hbyte_p p1 = (lzo_hbyte_p) dest; + const lzo_hbyte_p p2 = (const lzo_hbyte_p) src; + if (!(len > 0) || p1 == p2) + return dest; + if (p1 < p2) + { + do + *p1++ = *p2++; + while __lzo_likely(--len > 0); + } + else + { + p1 += len; + p2 += len; + do + *--p1 = *--p2; + while __lzo_likely(--len > 0); + } + return dest; +#else + return memmove(dest, src, len); +#endif +} +LZOLIB_PUBLIC(lzo_hvoid_p, lzo_hmemset) (lzo_hvoid_p s, int c, lzo_hsize_t len) +{ +#if (LZO_HAVE_MM_HUGE_PTR) || !defined(HAVE_MEMSET) + lzo_hbyte_p p = (lzo_hbyte_p) s; + if __lzo_likely(len > 0) do + *p++ = (unsigned char) c; + while __lzo_likely(--len > 0); + return s; +#else + return memset(s, c, len); +#endif +} +#undef LZOLIB_PUBLIC +#endif + +#if !defined(__LZO_IN_MINILZO) + +#define ACC_WANT_ACC_CHK_CH 1 +#undef ACCCHK_ASSERT + + ACCCHK_ASSERT_IS_SIGNED_T(lzo_int) + ACCCHK_ASSERT_IS_UNSIGNED_T(lzo_uint) + + ACCCHK_ASSERT_IS_SIGNED_T(lzo_int32) + ACCCHK_ASSERT_IS_UNSIGNED_T(lzo_uint32) + ACCCHK_ASSERT((LZO_UINT32_C(1) << (int)(8*sizeof(LZO_UINT32_C(1))-1)) > 0) + ACCCHK_ASSERT(sizeof(lzo_uint32) >= 4) + +#if !defined(__LZO_UINTPTR_T_IS_POINTER) + ACCCHK_ASSERT_IS_UNSIGNED_T(lzo_uintptr_t) +#endif + ACCCHK_ASSERT(sizeof(lzo_uintptr_t) >= sizeof(lzo_voidp)) + + ACCCHK_ASSERT_IS_UNSIGNED_T(lzo_xint) + ACCCHK_ASSERT(sizeof(lzo_xint) >= sizeof(lzo_uint32)) + ACCCHK_ASSERT(sizeof(lzo_xint) >= sizeof(lzo_uint)) + ACCCHK_ASSERT(sizeof(lzo_xint) == sizeof(lzo_uint32) || sizeof(lzo_xint) == sizeof(lzo_uint)) + +#endif +#undef ACCCHK_ASSERT + +LZO_PUBLIC(int) +_lzo_config_check(void) +{ + lzo_bool r = 1; + union { unsigned char c[2*sizeof(lzo_xint)]; lzo_xint l[2]; } u; + lzo_uintptr_t p; + +#if !defined(LZO_CFG_NO_CONFIG_CHECK) +#if defined(LZO_ABI_BIG_ENDIAN) + u.l[0] = u.l[1] = 0; u.c[sizeof(lzo_xint) - 1] = 128; + r &= (u.l[0] == 128); +#endif +#if defined(LZO_ABI_LITTLE_ENDIAN) + u.l[0] = u.l[1] = 0; u.c[0] = 128; + r &= (u.l[0] == 128); +#endif +#if defined(LZO_UNALIGNED_OK_2) + p = (lzo_uintptr_t) (const lzo_voidp) &u.c[0]; + u.l[0] = u.l[1] = 0; + r &= ((* (const lzo_ushortp) (p+1)) == 0); +#endif +#if defined(LZO_UNALIGNED_OK_4) + p = (lzo_uintptr_t) (const lzo_voidp) &u.c[0]; + u.l[0] = u.l[1] = 0; + r &= ((* (const lzo_uint32p) (p+1)) == 0); +#endif +#endif + + LZO_UNUSED(u); LZO_UNUSED(p); + return r == 1 ? LZO_E_OK : LZO_E_ERROR; +} + +int __lzo_init_done = 0; + +LZO_PUBLIC(int) +__lzo_init_v2(unsigned v, int s1, int s2, int s3, int s4, int s5, + int s6, int s7, int s8, int s9) +{ + int r; + +#if defined(__LZO_IN_MINILZO) +#elif (LZO_CC_MSC && ((_MSC_VER) < 700)) +#else +#define ACC_WANT_ACC_CHK_CH 1 +#undef ACCCHK_ASSERT +#define ACCCHK_ASSERT(expr) LZO_COMPILE_TIME_ASSERT(expr) +#endif +#undef ACCCHK_ASSERT + + __lzo_init_done = 1; + + if (v == 0) + return LZO_E_ERROR; + + r = (s1 == -1 || s1 == (int) sizeof(short)) && + (s2 == -1 || s2 == (int) sizeof(int)) && + (s3 == -1 || s3 == (int) sizeof(long)) && + (s4 == -1 || s4 == (int) sizeof(lzo_uint32)) && + (s5 == -1 || s5 == (int) sizeof(lzo_uint)) && + (s6 == -1 || s6 == (int) lzo_sizeof_dict_t) && + (s7 == -1 || s7 == (int) sizeof(char *)) && + (s8 == -1 || s8 == (int) sizeof(lzo_voidp)) && + (s9 == -1 || s9 == (int) sizeof(lzo_callback_t)); + if (!r) + return LZO_E_ERROR; + + r = _lzo_config_check(); + if (r != LZO_E_OK) + return r; + + return r; +} + +#if !defined(__LZO_IN_MINILZO) + +#if (LZO_OS_WIN16 && LZO_CC_WATCOMC) && defined(__SW_BD) + +#if 0 +BOOL FAR PASCAL LibMain ( HANDLE hInstance, WORD wDataSegment, + WORD wHeapSize, LPSTR lpszCmdLine ) +#else +int __far __pascal LibMain ( int a, short b, short c, long d ) +#endif +{ + LZO_UNUSED(a); LZO_UNUSED(b); LZO_UNUSED(c); LZO_UNUSED(d); + return 1; +} + +#endif + +#endif + +#define do_compress _lzo1x_1_do_compress + +#if !defined(MINILZO_CFG_SKIP_LZO1X_1_COMPRESS) + +#define LZO_NEED_DICT_H +#define D_BITS 14 +#define D_INDEX1(d,p) d = DM(DMUL(0x21,DX3(p,5,5,6)) >> 5) +#define D_INDEX2(d,p) d = (d & (D_MASK & 0x7ff)) ^ (D_HIGH | 0x1f) + +#ifndef __LZO_CONFIG1X_H +#define __LZO_CONFIG1X_H + +#if !defined(LZO1X) && !defined(LZO1Y) && !defined(LZO1Z) +# define LZO1X +#endif + +#if !defined(__LZO_IN_MINILZO) +#include "lzo/lzo1x.h" +#endif + +#define LZO_EOF_CODE +#undef LZO_DETERMINISTIC + +#define M1_MAX_OFFSET 0x0400 +#ifndef M2_MAX_OFFSET +#define M2_MAX_OFFSET 0x0800 +#endif +#define M3_MAX_OFFSET 0x4000 +#define M4_MAX_OFFSET 0xbfff + +#define MX_MAX_OFFSET (M1_MAX_OFFSET + M2_MAX_OFFSET) + +#define M1_MIN_LEN 2 +#define M1_MAX_LEN 2 +#define M2_MIN_LEN 3 +#ifndef M2_MAX_LEN +#define M2_MAX_LEN 8 +#endif +#define M3_MIN_LEN 3 +#define M3_MAX_LEN 33 +#define M4_MIN_LEN 3 +#define M4_MAX_LEN 9 + +#define M1_MARKER 0 +#define M2_MARKER 64 +#define M3_MARKER 32 +#define M4_MARKER 16 + +#ifndef MIN_LOOKAHEAD +#define MIN_LOOKAHEAD (M2_MAX_LEN + 1) +#endif + +#if defined(LZO_NEED_DICT_H) + +#ifndef LZO_HASH +#define LZO_HASH LZO_HASH_LZO_INCREMENTAL_B +#endif +#define DL_MIN_LEN M2_MIN_LEN + +#ifndef __LZO_DICT_H +#define __LZO_DICT_H + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(D_BITS) && defined(DBITS) +# define D_BITS DBITS +#endif +#if !defined(D_BITS) +# error "D_BITS is not defined" +#endif +#if (D_BITS < 16) +# define D_SIZE LZO_SIZE(D_BITS) +# define D_MASK LZO_MASK(D_BITS) +#else +# define D_SIZE LZO_USIZE(D_BITS) +# define D_MASK LZO_UMASK(D_BITS) +#endif +#define D_HIGH ((D_MASK >> 1) + 1) + +#if !defined(DD_BITS) +# define DD_BITS 0 +#endif +#define DD_SIZE LZO_SIZE(DD_BITS) +#define DD_MASK LZO_MASK(DD_BITS) + +#if !defined(DL_BITS) +# define DL_BITS (D_BITS - DD_BITS) +#endif +#if (DL_BITS < 16) +# define DL_SIZE LZO_SIZE(DL_BITS) +# define DL_MASK LZO_MASK(DL_BITS) +#else +# define DL_SIZE LZO_USIZE(DL_BITS) +# define DL_MASK LZO_UMASK(DL_BITS) +#endif + +#if (D_BITS != DL_BITS + DD_BITS) +# error "D_BITS does not match" +#endif +#if (D_BITS < 8 || D_BITS > 18) +# error "invalid D_BITS" +#endif +#if (DL_BITS < 8 || DL_BITS > 20) +# error "invalid DL_BITS" +#endif +#if (DD_BITS < 0 || DD_BITS > 6) +# error "invalid DD_BITS" +#endif + +#if !defined(DL_MIN_LEN) +# define DL_MIN_LEN 3 +#endif +#if !defined(DL_SHIFT) +# define DL_SHIFT ((DL_BITS + (DL_MIN_LEN - 1)) / DL_MIN_LEN) +#endif + +#define LZO_HASH_GZIP 1 +#define LZO_HASH_GZIP_INCREMENTAL 2 +#define LZO_HASH_LZO_INCREMENTAL_A 3 +#define LZO_HASH_LZO_INCREMENTAL_B 4 + +#if !defined(LZO_HASH) +# error "choose a hashing strategy" +#endif + +#undef DM +#undef DX + +#if (DL_MIN_LEN == 3) +# define _DV2_A(p,shift1,shift2) \ + (((( (lzo_xint)((p)[0]) << shift1) ^ (p)[1]) << shift2) ^ (p)[2]) +# define _DV2_B(p,shift1,shift2) \ + (((( (lzo_xint)((p)[2]) << shift1) ^ (p)[1]) << shift2) ^ (p)[0]) +# define _DV3_B(p,shift1,shift2,shift3) \ + ((_DV2_B((p)+1,shift1,shift2) << (shift3)) ^ (p)[0]) +#elif (DL_MIN_LEN == 2) +# define _DV2_A(p,shift1,shift2) \ + (( (lzo_xint)(p[0]) << shift1) ^ p[1]) +# define _DV2_B(p,shift1,shift2) \ + (( (lzo_xint)(p[1]) << shift1) ^ p[2]) +#else +# error "invalid DL_MIN_LEN" +#endif +#define _DV_A(p,shift) _DV2_A(p,shift,shift) +#define _DV_B(p,shift) _DV2_B(p,shift,shift) +#define DA2(p,s1,s2) \ + (((((lzo_xint)((p)[2]) << (s2)) + (p)[1]) << (s1)) + (p)[0]) +#define DS2(p,s1,s2) \ + (((((lzo_xint)((p)[2]) << (s2)) - (p)[1]) << (s1)) - (p)[0]) +#define DX2(p,s1,s2) \ + (((((lzo_xint)((p)[2]) << (s2)) ^ (p)[1]) << (s1)) ^ (p)[0]) +#define DA3(p,s1,s2,s3) ((DA2((p)+1,s2,s3) << (s1)) + (p)[0]) +#define DS3(p,s1,s2,s3) ((DS2((p)+1,s2,s3) << (s1)) - (p)[0]) +#define DX3(p,s1,s2,s3) ((DX2((p)+1,s2,s3) << (s1)) ^ (p)[0]) +#define DMS(v,s) ((lzo_uint) (((v) & (D_MASK >> (s))) << (s))) +#define DM(v) DMS(v,0) + +#if (LZO_HASH == LZO_HASH_GZIP) +# define _DINDEX(dv,p) (_DV_A((p),DL_SHIFT)) + +#elif (LZO_HASH == LZO_HASH_GZIP_INCREMENTAL) +# define __LZO_HASH_INCREMENTAL +# define DVAL_FIRST(dv,p) dv = _DV_A((p),DL_SHIFT) +# define DVAL_NEXT(dv,p) dv = (((dv) << DL_SHIFT) ^ p[2]) +# define _DINDEX(dv,p) (dv) +# define DVAL_LOOKAHEAD DL_MIN_LEN + +#elif (LZO_HASH == LZO_HASH_LZO_INCREMENTAL_A) +# define __LZO_HASH_INCREMENTAL +# define DVAL_FIRST(dv,p) dv = _DV_A((p),5) +# define DVAL_NEXT(dv,p) \ + dv ^= (lzo_xint)(p[-1]) << (2*5); dv = (((dv) << 5) ^ p[2]) +# define _DINDEX(dv,p) ((DMUL(0x9f5f,dv)) >> 5) +# define DVAL_LOOKAHEAD DL_MIN_LEN + +#elif (LZO_HASH == LZO_HASH_LZO_INCREMENTAL_B) +# define __LZO_HASH_INCREMENTAL +# define DVAL_FIRST(dv,p) dv = _DV_B((p),5) +# define DVAL_NEXT(dv,p) \ + dv ^= p[-1]; dv = (((dv) >> 5) ^ ((lzo_xint)(p[2]) << (2*5))) +# define _DINDEX(dv,p) ((DMUL(0x9f5f,dv)) >> 5) +# define DVAL_LOOKAHEAD DL_MIN_LEN + +#else +# error "choose a hashing strategy" +#endif + +#ifndef DINDEX +#define DINDEX(dv,p) ((lzo_uint)((_DINDEX(dv,p)) & DL_MASK) << DD_BITS) +#endif +#if !defined(DINDEX1) && defined(D_INDEX1) +#define DINDEX1 D_INDEX1 +#endif +#if !defined(DINDEX2) && defined(D_INDEX2) +#define DINDEX2 D_INDEX2 +#endif + +#if !defined(__LZO_HASH_INCREMENTAL) +# define DVAL_FIRST(dv,p) ((void) 0) +# define DVAL_NEXT(dv,p) ((void) 0) +# define DVAL_LOOKAHEAD 0 +#endif + +#if !defined(DVAL_ASSERT) +#if defined(__LZO_HASH_INCREMENTAL) && !defined(NDEBUG) +static void DVAL_ASSERT(lzo_xint dv, const lzo_bytep p) +{ + lzo_xint df; + DVAL_FIRST(df,(p)); + assert(DINDEX(dv,p) == DINDEX(df,p)); +} +#else +# define DVAL_ASSERT(dv,p) ((void) 0) +#endif +#endif + +#if defined(LZO_DICT_USE_PTR) +# define DENTRY(p,in) (p) +# define GINDEX(m_pos,m_off,dict,dindex,in) m_pos = dict[dindex] +#else +# define DENTRY(p,in) ((lzo_uint) ((p)-(in))) +# define GINDEX(m_pos,m_off,dict,dindex,in) m_off = dict[dindex] +#endif + +#if (DD_BITS == 0) + +# define UPDATE_D(dict,drun,dv,p,in) dict[ DINDEX(dv,p) ] = DENTRY(p,in) +# define UPDATE_I(dict,drun,index,p,in) dict[index] = DENTRY(p,in) +# define UPDATE_P(ptr,drun,p,in) (ptr)[0] = DENTRY(p,in) + +#else + +# define UPDATE_D(dict,drun,dv,p,in) \ + dict[ DINDEX(dv,p) + drun++ ] = DENTRY(p,in); drun &= DD_MASK +# define UPDATE_I(dict,drun,index,p,in) \ + dict[ (index) + drun++ ] = DENTRY(p,in); drun &= DD_MASK +# define UPDATE_P(ptr,drun,p,in) \ + (ptr) [ drun++ ] = DENTRY(p,in); drun &= DD_MASK + +#endif + +#if defined(LZO_DICT_USE_PTR) + +#define LZO_CHECK_MPOS_DET(m_pos,m_off,in,ip,max_offset) \ + (m_pos == NULL || (m_off = pd(ip, m_pos)) > max_offset) + +#define LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,max_offset) \ + (BOUNDS_CHECKING_OFF_IN_EXPR(( \ + m_pos = ip - (lzo_uint) PTR_DIFF(ip,m_pos), \ + PTR_LT(m_pos,in) || \ + (m_off = (lzo_uint) PTR_DIFF(ip,m_pos)) <= 0 || \ + m_off > max_offset ))) + +#else + +#define LZO_CHECK_MPOS_DET(m_pos,m_off,in,ip,max_offset) \ + (m_off == 0 || \ + ((m_off = pd(ip, in) - m_off) > max_offset) || \ + (m_pos = (ip) - (m_off), 0) ) + +#define LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,max_offset) \ + (pd(ip, in) <= m_off || \ + ((m_off = pd(ip, in) - m_off) > max_offset) || \ + (m_pos = (ip) - (m_off), 0) ) + +#endif + +#if defined(LZO_DETERMINISTIC) +# define LZO_CHECK_MPOS LZO_CHECK_MPOS_DET +#else +# define LZO_CHECK_MPOS LZO_CHECK_MPOS_NON_DET +#endif + +#ifdef __cplusplus +} +#endif + +#endif + +#endif + +#endif + +#define DO_COMPRESS lzo1x_1_compress + +static __lzo_noinline lzo_uint +do_compress ( const lzo_bytep in , lzo_uint in_len, + lzo_bytep out, lzo_uintp out_len, + lzo_voidp wrkmem ) +{ + register const lzo_bytep ip; + lzo_bytep op; + const lzo_bytep const in_end = in + in_len; + const lzo_bytep const ip_end = in + in_len - M2_MAX_LEN - 5; + const lzo_bytep ii; + lzo_dict_p const dict = (lzo_dict_p) wrkmem; + + op = out; + ip = in; + ii = ip; + + ip += 4; + for (;;) + { + register const lzo_bytep m_pos; + lzo_uint m_off; + lzo_uint m_len; + lzo_uint dindex; + + DINDEX1(dindex,ip); + GINDEX(m_pos,m_off,dict,dindex,in); + if (LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,M4_MAX_OFFSET)) + goto literal; +#if 1 + if (m_off <= M2_MAX_OFFSET || m_pos[3] == ip[3]) + goto try_match; + DINDEX2(dindex,ip); +#endif + GINDEX(m_pos,m_off,dict,dindex,in); + if (LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,M4_MAX_OFFSET)) + goto literal; + if (m_off <= M2_MAX_OFFSET || m_pos[3] == ip[3]) + goto try_match; + goto literal; + +try_match: +#if 1 && defined(LZO_UNALIGNED_OK_2) + if (* (const lzo_ushortp) m_pos != * (const lzo_ushortp) ip) +#else + if (m_pos[0] != ip[0] || m_pos[1] != ip[1]) +#endif + { + } + else + { + if __lzo_likely(m_pos[2] == ip[2]) + { +#if 0 + if (m_off <= M2_MAX_OFFSET) + goto match; + if (lit <= 3) + goto match; + if (lit == 3) + { + assert(op - 2 > out); op[-2] |= LZO_BYTE(3); + *op++ = *ii++; *op++ = *ii++; *op++ = *ii++; + goto code_match; + } + if (m_pos[3] == ip[3]) +#endif + goto match; + } + else + { +#if 0 +#if 0 + if (m_off <= M1_MAX_OFFSET && lit > 0 && lit <= 3) +#else + if (m_off <= M1_MAX_OFFSET && lit == 3) +#endif + { + register lzo_uint t; + + t = lit; + assert(op - 2 > out); op[-2] |= LZO_BYTE(t); + do *op++ = *ii++; while (--t > 0); + assert(ii == ip); + m_off -= 1; + *op++ = LZO_BYTE(M1_MARKER | ((m_off & 3) << 2)); + *op++ = LZO_BYTE(m_off >> 2); + ip += 2; + goto match_done; + } +#endif + } + } + +literal: + UPDATE_I(dict,0,dindex,ip,in); + ++ip; + if __lzo_unlikely(ip >= ip_end) + break; + continue; + +match: + UPDATE_I(dict,0,dindex,ip,in); + if (pd(ip,ii) > 0) + { + register lzo_uint t = pd(ip,ii); + + if (t <= 3) + { + assert(op - 2 > out); + op[-2] |= LZO_BYTE(t); + } + else if (t <= 18) + *op++ = LZO_BYTE(t - 3); + else + { + register lzo_uint tt = t - 18; + + *op++ = 0; + while (tt > 255) + { + tt -= 255; + *op++ = 0; + } + assert(tt > 0); + *op++ = LZO_BYTE(tt); + } + do *op++ = *ii++; while (--t > 0); + } + + assert(ii == ip); + ip += 3; + if (m_pos[3] != *ip++ || m_pos[4] != *ip++ || m_pos[5] != *ip++ || + m_pos[6] != *ip++ || m_pos[7] != *ip++ || m_pos[8] != *ip++ +#ifdef LZO1Y + || m_pos[ 9] != *ip++ || m_pos[10] != *ip++ || m_pos[11] != *ip++ + || m_pos[12] != *ip++ || m_pos[13] != *ip++ || m_pos[14] != *ip++ +#endif + ) + { + --ip; + m_len = pd(ip, ii); + assert(m_len >= 3); assert(m_len <= M2_MAX_LEN); + + if (m_off <= M2_MAX_OFFSET) + { + m_off -= 1; +#if defined(LZO1X) + *op++ = LZO_BYTE(((m_len - 1) << 5) | ((m_off & 7) << 2)); + *op++ = LZO_BYTE(m_off >> 3); +#elif defined(LZO1Y) + *op++ = LZO_BYTE(((m_len + 1) << 4) | ((m_off & 3) << 2)); + *op++ = LZO_BYTE(m_off >> 2); +#endif + } + else if (m_off <= M3_MAX_OFFSET) + { + m_off -= 1; + *op++ = LZO_BYTE(M3_MARKER | (m_len - 2)); + goto m3_m4_offset; + } + else +#if defined(LZO1X) + { + m_off -= 0x4000; + assert(m_off > 0); assert(m_off <= 0x7fff); + *op++ = LZO_BYTE(M4_MARKER | + ((m_off & 0x4000) >> 11) | (m_len - 2)); + goto m3_m4_offset; + } +#elif defined(LZO1Y) + goto m4_match; +#endif + } + else + { + { + const lzo_bytep end = in_end; + const lzo_bytep m = m_pos + M2_MAX_LEN + 1; + while (ip < end && *m == *ip) + m++, ip++; + m_len = pd(ip, ii); + } + assert(m_len > M2_MAX_LEN); + + if (m_off <= M3_MAX_OFFSET) + { + m_off -= 1; + if (m_len <= 33) + *op++ = LZO_BYTE(M3_MARKER | (m_len - 2)); + else + { + m_len -= 33; + *op++ = M3_MARKER | 0; + goto m3_m4_len; + } + } + else + { +#if defined(LZO1Y) +m4_match: +#endif + m_off -= 0x4000; + assert(m_off > 0); assert(m_off <= 0x7fff); + if (m_len <= M4_MAX_LEN) + *op++ = LZO_BYTE(M4_MARKER | + ((m_off & 0x4000) >> 11) | (m_len - 2)); + else + { + m_len -= M4_MAX_LEN; + *op++ = LZO_BYTE(M4_MARKER | ((m_off & 0x4000) >> 11)); +m3_m4_len: + while (m_len > 255) + { + m_len -= 255; + *op++ = 0; + } + assert(m_len > 0); + *op++ = LZO_BYTE(m_len); + } + } + +m3_m4_offset: + *op++ = LZO_BYTE((m_off & 63) << 2); + *op++ = LZO_BYTE(m_off >> 6); + } + +#if 0 +match_done: +#endif + ii = ip; + if __lzo_unlikely(ip >= ip_end) + break; + } + + *out_len = pd(op, out); + return pd(in_end,ii); +} + +LZO_PUBLIC(int) +DO_COMPRESS ( const lzo_bytep in , lzo_uint in_len, + lzo_bytep out, lzo_uintp out_len, + lzo_voidp wrkmem ) +{ + lzo_bytep op = out; + lzo_uint t; + + if __lzo_unlikely(in_len <= M2_MAX_LEN + 5) + t = in_len; + else + { + t = do_compress(in,in_len,op,out_len,wrkmem); + op += *out_len; + } + + if (t > 0) + { + const lzo_bytep ii = in + in_len - t; + + if (op == out && t <= 238) + *op++ = LZO_BYTE(17 + t); + else if (t <= 3) + op[-2] |= LZO_BYTE(t); + else if (t <= 18) + *op++ = LZO_BYTE(t - 3); + else + { + lzo_uint tt = t - 18; + + *op++ = 0; + while (tt > 255) + { + tt -= 255; + *op++ = 0; + } + assert(tt > 0); + *op++ = LZO_BYTE(tt); + } + do *op++ = *ii++; while (--t > 0); + } + + *op++ = M4_MARKER | 1; + *op++ = 0; + *op++ = 0; + + *out_len = pd(op, out); + return LZO_E_OK; +} + +#endif + +#undef do_compress +#undef DO_COMPRESS +#undef LZO_HASH + +#undef LZO_TEST_OVERRUN +#undef DO_DECOMPRESS +#define DO_DECOMPRESS lzo1x_decompress + +#if !defined(MINILZO_CFG_SKIP_LZO1X_DECOMPRESS) + +#if defined(LZO_TEST_OVERRUN) +# if !defined(LZO_TEST_OVERRUN_INPUT) +# define LZO_TEST_OVERRUN_INPUT 2 +# endif +# if !defined(LZO_TEST_OVERRUN_OUTPUT) +# define LZO_TEST_OVERRUN_OUTPUT 2 +# endif +# if !defined(LZO_TEST_OVERRUN_LOOKBEHIND) +# define LZO_TEST_OVERRUN_LOOKBEHIND +# endif +#endif + +#undef TEST_IP +#undef TEST_OP +#undef TEST_LB +#undef TEST_LBO +#undef NEED_IP +#undef NEED_OP +#undef HAVE_TEST_IP +#undef HAVE_TEST_OP +#undef HAVE_NEED_IP +#undef HAVE_NEED_OP +#undef HAVE_ANY_IP +#undef HAVE_ANY_OP + +#if defined(LZO_TEST_OVERRUN_INPUT) +# if (LZO_TEST_OVERRUN_INPUT >= 1) +# define TEST_IP (ip < ip_end) +# endif +# if (LZO_TEST_OVERRUN_INPUT >= 2) +# define NEED_IP(x) \ + if ((lzo_uint)(ip_end - ip) < (lzo_uint)(x)) goto input_overrun +# endif +#endif + +#if defined(LZO_TEST_OVERRUN_OUTPUT) +# if (LZO_TEST_OVERRUN_OUTPUT >= 1) +# define TEST_OP (op <= op_end) +# endif +# if (LZO_TEST_OVERRUN_OUTPUT >= 2) +# undef TEST_OP +# define NEED_OP(x) \ + if ((lzo_uint)(op_end - op) < (lzo_uint)(x)) goto output_overrun +# endif +#endif + +#if defined(LZO_TEST_OVERRUN_LOOKBEHIND) +# define TEST_LB(m_pos) if (m_pos < out || m_pos >= op) goto lookbehind_overrun +# define TEST_LBO(m_pos,o) if (m_pos < out || m_pos >= op - (o)) goto lookbehind_overrun +#else +# define TEST_LB(m_pos) ((void) 0) +# define TEST_LBO(m_pos,o) ((void) 0) +#endif + +#if !defined(LZO_EOF_CODE) && !defined(TEST_IP) +# define TEST_IP (ip < ip_end) +#endif + +#if defined(TEST_IP) +# define HAVE_TEST_IP +#else +# define TEST_IP 1 +#endif +#if defined(TEST_OP) +# define HAVE_TEST_OP +#else +# define TEST_OP 1 +#endif + +#if defined(NEED_IP) +# define HAVE_NEED_IP +#else +# define NEED_IP(x) ((void) 0) +#endif +#if defined(NEED_OP) +# define HAVE_NEED_OP +#else +# define NEED_OP(x) ((void) 0) +#endif + +#if defined(HAVE_TEST_IP) || defined(HAVE_NEED_IP) +# define HAVE_ANY_IP +#endif +#if defined(HAVE_TEST_OP) || defined(HAVE_NEED_OP) +# define HAVE_ANY_OP +#endif + +#undef __COPY4 +#define __COPY4(dst,src) * (lzo_uint32p)(dst) = * (const lzo_uint32p)(src) + +#undef COPY4 +#if defined(LZO_UNALIGNED_OK_4) +# define COPY4(dst,src) __COPY4(dst,src) +#elif defined(LZO_ALIGNED_OK_4) +# define COPY4(dst,src) __COPY4((lzo_uintptr_t)(dst),(lzo_uintptr_t)(src)) +#endif + +#if defined(DO_DECOMPRESS) +LZO_PUBLIC(int) +DO_DECOMPRESS ( const lzo_bytep in , lzo_uint in_len, + lzo_bytep out, lzo_uintp out_len, + lzo_voidp wrkmem ) +#endif +{ + register lzo_bytep op; + register const lzo_bytep ip; + register lzo_uint t; +#if defined(COPY_DICT) + lzo_uint m_off; + const lzo_bytep dict_end; +#else + register const lzo_bytep m_pos; +#endif + + const lzo_bytep const ip_end = in + in_len; +#if defined(HAVE_ANY_OP) + lzo_bytep const op_end = out + *out_len; +#endif +#if defined(LZO1Z) + lzo_uint last_m_off = 0; +#endif + + LZO_UNUSED(wrkmem); + +#if defined(COPY_DICT) + if (dict) + { + if (dict_len > M4_MAX_OFFSET) + { + dict += dict_len - M4_MAX_OFFSET; + dict_len = M4_MAX_OFFSET; + } + dict_end = dict + dict_len; + } + else + { + dict_len = 0; + dict_end = NULL; + } +#endif + + *out_len = 0; + + op = out; + ip = in; + + if (*ip > 17) + { + t = *ip++ - 17; + if (t < 4) + goto match_next; + assert(t > 0); NEED_OP(t); NEED_IP(t+1); + do *op++ = *ip++; while (--t > 0); + goto first_literal_run; + } + + while (TEST_IP && TEST_OP) + { + t = *ip++; + if (t >= 16) + goto match; + if (t == 0) + { + NEED_IP(1); + while (*ip == 0) + { + t += 255; + ip++; + NEED_IP(1); + } + t += 15 + *ip++; + } + assert(t > 0); NEED_OP(t+3); NEED_IP(t+4); +#if defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4) +#if !defined(LZO_UNALIGNED_OK_4) + if (PTR_ALIGNED2_4(op,ip)) + { +#endif + COPY4(op,ip); + op += 4; ip += 4; + if (--t > 0) + { + if (t >= 4) + { + do { + COPY4(op,ip); + op += 4; ip += 4; t -= 4; + } while (t >= 4); + if (t > 0) do *op++ = *ip++; while (--t > 0); + } + else + do *op++ = *ip++; while (--t > 0); + } +#if !defined(LZO_UNALIGNED_OK_4) + } + else +#endif +#endif +#if !defined(LZO_UNALIGNED_OK_4) + { + *op++ = *ip++; *op++ = *ip++; *op++ = *ip++; + do *op++ = *ip++; while (--t > 0); + } +#endif + +first_literal_run: + + t = *ip++; + if (t >= 16) + goto match; +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2); + last_m_off = m_off; +#else + m_off = (1 + M2_MAX_OFFSET) + (t >> 2) + (*ip++ << 2); +#endif + NEED_OP(3); + t = 3; COPY_DICT(t,m_off) +#else +#if defined(LZO1Z) + t = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2); + m_pos = op - t; + last_m_off = t; +#else + m_pos = op - (1 + M2_MAX_OFFSET); + m_pos -= t >> 2; + m_pos -= *ip++ << 2; +#endif + TEST_LB(m_pos); NEED_OP(3); + *op++ = *m_pos++; *op++ = *m_pos++; *op++ = *m_pos; +#endif + goto match_done; + + do { +match: + if (t >= 64) + { +#if defined(COPY_DICT) +#if defined(LZO1X) + m_off = 1 + ((t >> 2) & 7) + (*ip++ << 3); + t = (t >> 5) - 1; +#elif defined(LZO1Y) + m_off = 1 + ((t >> 2) & 3) + (*ip++ << 2); + t = (t >> 4) - 3; +#elif defined(LZO1Z) + m_off = t & 0x1f; + if (m_off >= 0x1c) + m_off = last_m_off; + else + { + m_off = 1 + (m_off << 6) + (*ip++ >> 2); + last_m_off = m_off; + } + t = (t >> 5) - 1; +#endif +#else +#if defined(LZO1X) + m_pos = op - 1; + m_pos -= (t >> 2) & 7; + m_pos -= *ip++ << 3; + t = (t >> 5) - 1; +#elif defined(LZO1Y) + m_pos = op - 1; + m_pos -= (t >> 2) & 3; + m_pos -= *ip++ << 2; + t = (t >> 4) - 3; +#elif defined(LZO1Z) + { + lzo_uint off = t & 0x1f; + m_pos = op; + if (off >= 0x1c) + { + assert(last_m_off > 0); + m_pos -= last_m_off; + } + else + { + off = 1 + (off << 6) + (*ip++ >> 2); + m_pos -= off; + last_m_off = off; + } + } + t = (t >> 5) - 1; +#endif + TEST_LB(m_pos); assert(t > 0); NEED_OP(t+3-1); + goto copy_match; +#endif + } + else if (t >= 32) + { + t &= 31; + if (t == 0) + { + NEED_IP(1); + while (*ip == 0) + { + t += 255; + ip++; + NEED_IP(1); + } + t += 31 + *ip++; + } +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off = 1 + (ip[0] << 6) + (ip[1] >> 2); + last_m_off = m_off; +#else + m_off = 1 + (ip[0] >> 2) + (ip[1] << 6); +#endif +#else +#if defined(LZO1Z) + { + lzo_uint off = 1 + (ip[0] << 6) + (ip[1] >> 2); + m_pos = op - off; + last_m_off = off; + } +#elif defined(LZO_UNALIGNED_OK_2) && defined(LZO_ABI_LITTLE_ENDIAN) + m_pos = op - 1; + m_pos -= (* (const lzo_ushortp) ip) >> 2; +#else + m_pos = op - 1; + m_pos -= (ip[0] >> 2) + (ip[1] << 6); +#endif +#endif + ip += 2; + } + else if (t >= 16) + { +#if defined(COPY_DICT) + m_off = (t & 8) << 11; +#else + m_pos = op; + m_pos -= (t & 8) << 11; +#endif + t &= 7; + if (t == 0) + { + NEED_IP(1); + while (*ip == 0) + { + t += 255; + ip++; + NEED_IP(1); + } + t += 7 + *ip++; + } +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off += (ip[0] << 6) + (ip[1] >> 2); +#else + m_off += (ip[0] >> 2) + (ip[1] << 6); +#endif + ip += 2; + if (m_off == 0) + goto eof_found; + m_off += 0x4000; +#if defined(LZO1Z) + last_m_off = m_off; +#endif +#else +#if defined(LZO1Z) + m_pos -= (ip[0] << 6) + (ip[1] >> 2); +#elif defined(LZO_UNALIGNED_OK_2) && defined(LZO_ABI_LITTLE_ENDIAN) + m_pos -= (* (const lzo_ushortp) ip) >> 2; +#else + m_pos -= (ip[0] >> 2) + (ip[1] << 6); +#endif + ip += 2; + if (m_pos == op) + goto eof_found; + m_pos -= 0x4000; +#if defined(LZO1Z) + last_m_off = pd((const lzo_bytep)op, m_pos); +#endif +#endif + } + else + { +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off = 1 + (t << 6) + (*ip++ >> 2); + last_m_off = m_off; +#else + m_off = 1 + (t >> 2) + (*ip++ << 2); +#endif + NEED_OP(2); + t = 2; COPY_DICT(t,m_off) +#else +#if defined(LZO1Z) + t = 1 + (t << 6) + (*ip++ >> 2); + m_pos = op - t; + last_m_off = t; +#else + m_pos = op - 1; + m_pos -= t >> 2; + m_pos -= *ip++ << 2; +#endif + TEST_LB(m_pos); NEED_OP(2); + *op++ = *m_pos++; *op++ = *m_pos; +#endif + goto match_done; + } + +#if defined(COPY_DICT) + + NEED_OP(t+3-1); + t += 3-1; COPY_DICT(t,m_off) + +#else + + TEST_LB(m_pos); assert(t > 0); NEED_OP(t+3-1); +#if defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4) +#if !defined(LZO_UNALIGNED_OK_4) + if (t >= 2 * 4 - (3 - 1) && PTR_ALIGNED2_4(op,m_pos)) + { + assert((op - m_pos) >= 4); +#else + if (t >= 2 * 4 - (3 - 1) && (op - m_pos) >= 4) + { +#endif + COPY4(op,m_pos); + op += 4; m_pos += 4; t -= 4 - (3 - 1); + do { + COPY4(op,m_pos); + op += 4; m_pos += 4; t -= 4; + } while (t >= 4); + if (t > 0) do *op++ = *m_pos++; while (--t > 0); + } + else +#endif + { +copy_match: + *op++ = *m_pos++; *op++ = *m_pos++; + do *op++ = *m_pos++; while (--t > 0); + } + +#endif + +match_done: +#if defined(LZO1Z) + t = ip[-1] & 3; +#else + t = ip[-2] & 3; +#endif + if (t == 0) + break; + +match_next: + assert(t > 0); assert(t < 4); NEED_OP(t); NEED_IP(t+1); +#if 0 + do *op++ = *ip++; while (--t > 0); +#else + *op++ = *ip++; + if (t > 1) { *op++ = *ip++; if (t > 2) { *op++ = *ip++; } } +#endif + t = *ip++; + } while (TEST_IP && TEST_OP); + } + +#if defined(HAVE_TEST_IP) || defined(HAVE_TEST_OP) + *out_len = pd(op, out); + return LZO_E_EOF_NOT_FOUND; +#endif + +eof_found: + assert(t == 1); + *out_len = pd(op, out); + return (ip == ip_end ? LZO_E_OK : + (ip < ip_end ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN)); + +#if defined(HAVE_NEED_IP) +input_overrun: + *out_len = pd(op, out); + return LZO_E_INPUT_OVERRUN; +#endif + +#if defined(HAVE_NEED_OP) +output_overrun: + *out_len = pd(op, out); + return LZO_E_OUTPUT_OVERRUN; +#endif + +#if defined(LZO_TEST_OVERRUN_LOOKBEHIND) +lookbehind_overrun: + *out_len = pd(op, out); + return LZO_E_LOOKBEHIND_OVERRUN; +#endif +} + +#endif + +#define LZO_TEST_OVERRUN +#undef DO_DECOMPRESS +#define DO_DECOMPRESS lzo1x_decompress_safe + +#if !defined(MINILZO_CFG_SKIP_LZO1X_DECOMPRESS_SAFE) + +#if defined(LZO_TEST_OVERRUN) +# if !defined(LZO_TEST_OVERRUN_INPUT) +# define LZO_TEST_OVERRUN_INPUT 2 +# endif +# if !defined(LZO_TEST_OVERRUN_OUTPUT) +# define LZO_TEST_OVERRUN_OUTPUT 2 +# endif +# if !defined(LZO_TEST_OVERRUN_LOOKBEHIND) +# define LZO_TEST_OVERRUN_LOOKBEHIND +# endif +#endif + +#undef TEST_IP +#undef TEST_OP +#undef TEST_LB +#undef TEST_LBO +#undef NEED_IP +#undef NEED_OP +#undef HAVE_TEST_IP +#undef HAVE_TEST_OP +#undef HAVE_NEED_IP +#undef HAVE_NEED_OP +#undef HAVE_ANY_IP +#undef HAVE_ANY_OP + +#if defined(LZO_TEST_OVERRUN_INPUT) +# if (LZO_TEST_OVERRUN_INPUT >= 1) +# define TEST_IP (ip < ip_end) +# endif +# if (LZO_TEST_OVERRUN_INPUT >= 2) +# define NEED_IP(x) \ + if ((lzo_uint)(ip_end - ip) < (lzo_uint)(x)) goto input_overrun +# endif +#endif + +#if defined(LZO_TEST_OVERRUN_OUTPUT) +# if (LZO_TEST_OVERRUN_OUTPUT >= 1) +# define TEST_OP (op <= op_end) +# endif +# if (LZO_TEST_OVERRUN_OUTPUT >= 2) +# undef TEST_OP +# define NEED_OP(x) \ + if ((lzo_uint)(op_end - op) < (lzo_uint)(x)) goto output_overrun +# endif +#endif + +#if defined(LZO_TEST_OVERRUN_LOOKBEHIND) +# define TEST_LB(m_pos) if (m_pos < out || m_pos >= op) goto lookbehind_overrun +# define TEST_LBO(m_pos,o) if (m_pos < out || m_pos >= op - (o)) goto lookbehind_overrun +#else +# define TEST_LB(m_pos) ((void) 0) +# define TEST_LBO(m_pos,o) ((void) 0) +#endif + +#if !defined(LZO_EOF_CODE) && !defined(TEST_IP) +# define TEST_IP (ip < ip_end) +#endif + +#if defined(TEST_IP) +# define HAVE_TEST_IP +#else +# define TEST_IP 1 +#endif +#if defined(TEST_OP) +# define HAVE_TEST_OP +#else +# define TEST_OP 1 +#endif + +#if defined(NEED_IP) +# define HAVE_NEED_IP +#else +# define NEED_IP(x) ((void) 0) +#endif +#if defined(NEED_OP) +# define HAVE_NEED_OP +#else +# define NEED_OP(x) ((void) 0) +#endif + +#if defined(HAVE_TEST_IP) || defined(HAVE_NEED_IP) +# define HAVE_ANY_IP +#endif +#if defined(HAVE_TEST_OP) || defined(HAVE_NEED_OP) +# define HAVE_ANY_OP +#endif + +#undef __COPY4 +#define __COPY4(dst,src) * (lzo_uint32p)(dst) = * (const lzo_uint32p)(src) + +#undef COPY4 +#if defined(LZO_UNALIGNED_OK_4) +# define COPY4(dst,src) __COPY4(dst,src) +#elif defined(LZO_ALIGNED_OK_4) +# define COPY4(dst,src) __COPY4((lzo_uintptr_t)(dst),(lzo_uintptr_t)(src)) +#endif + +#if defined(DO_DECOMPRESS) +LZO_PUBLIC(int) +DO_DECOMPRESS ( const lzo_bytep in , lzo_uint in_len, + lzo_bytep out, lzo_uintp out_len, + lzo_voidp wrkmem ) +#endif +{ + register lzo_bytep op; + register const lzo_bytep ip; + register lzo_uint t; +#if defined(COPY_DICT) + lzo_uint m_off; + const lzo_bytep dict_end; +#else + register const lzo_bytep m_pos; +#endif + + const lzo_bytep const ip_end = in + in_len; +#if defined(HAVE_ANY_OP) + lzo_bytep const op_end = out + *out_len; +#endif +#if defined(LZO1Z) + lzo_uint last_m_off = 0; +#endif + + LZO_UNUSED(wrkmem); + +#if defined(COPY_DICT) + if (dict) + { + if (dict_len > M4_MAX_OFFSET) + { + dict += dict_len - M4_MAX_OFFSET; + dict_len = M4_MAX_OFFSET; + } + dict_end = dict + dict_len; + } + else + { + dict_len = 0; + dict_end = NULL; + } +#endif + + *out_len = 0; + + op = out; + ip = in; + + if (*ip > 17) + { + t = *ip++ - 17; + if (t < 4) + goto match_next; + assert(t > 0); NEED_OP(t); NEED_IP(t+1); + do *op++ = *ip++; while (--t > 0); + goto first_literal_run; + } + + while (TEST_IP && TEST_OP) + { + t = *ip++; + if (t >= 16) + goto match; + if (t == 0) + { + NEED_IP(1); + while (*ip == 0) + { + t += 255; + ip++; + NEED_IP(1); + } + t += 15 + *ip++; + } + assert(t > 0); NEED_OP(t+3); NEED_IP(t+4); +#if defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4) +#if !defined(LZO_UNALIGNED_OK_4) + if (PTR_ALIGNED2_4(op,ip)) + { +#endif + COPY4(op,ip); + op += 4; ip += 4; + if (--t > 0) + { + if (t >= 4) + { + do { + COPY4(op,ip); + op += 4; ip += 4; t -= 4; + } while (t >= 4); + if (t > 0) do *op++ = *ip++; while (--t > 0); + } + else + do *op++ = *ip++; while (--t > 0); + } +#if !defined(LZO_UNALIGNED_OK_4) + } + else +#endif +#endif +#if !defined(LZO_UNALIGNED_OK_4) + { + *op++ = *ip++; *op++ = *ip++; *op++ = *ip++; + do *op++ = *ip++; while (--t > 0); + } +#endif + +first_literal_run: + + t = *ip++; + if (t >= 16) + goto match; +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2); + last_m_off = m_off; +#else + m_off = (1 + M2_MAX_OFFSET) + (t >> 2) + (*ip++ << 2); +#endif + NEED_OP(3); + t = 3; COPY_DICT(t,m_off) +#else +#if defined(LZO1Z) + t = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2); + m_pos = op - t; + last_m_off = t; +#else + m_pos = op - (1 + M2_MAX_OFFSET); + m_pos -= t >> 2; + m_pos -= *ip++ << 2; +#endif + TEST_LB(m_pos); NEED_OP(3); + *op++ = *m_pos++; *op++ = *m_pos++; *op++ = *m_pos; +#endif + goto match_done; + + do { +match: + if (t >= 64) + { +#if defined(COPY_DICT) +#if defined(LZO1X) + m_off = 1 + ((t >> 2) & 7) + (*ip++ << 3); + t = (t >> 5) - 1; +#elif defined(LZO1Y) + m_off = 1 + ((t >> 2) & 3) + (*ip++ << 2); + t = (t >> 4) - 3; +#elif defined(LZO1Z) + m_off = t & 0x1f; + if (m_off >= 0x1c) + m_off = last_m_off; + else + { + m_off = 1 + (m_off << 6) + (*ip++ >> 2); + last_m_off = m_off; + } + t = (t >> 5) - 1; +#endif +#else +#if defined(LZO1X) + m_pos = op - 1; + m_pos -= (t >> 2) & 7; + m_pos -= *ip++ << 3; + t = (t >> 5) - 1; +#elif defined(LZO1Y) + m_pos = op - 1; + m_pos -= (t >> 2) & 3; + m_pos -= *ip++ << 2; + t = (t >> 4) - 3; +#elif defined(LZO1Z) + { + lzo_uint off = t & 0x1f; + m_pos = op; + if (off >= 0x1c) + { + assert(last_m_off > 0); + m_pos -= last_m_off; + } + else + { + off = 1 + (off << 6) + (*ip++ >> 2); + m_pos -= off; + last_m_off = off; + } + } + t = (t >> 5) - 1; +#endif + TEST_LB(m_pos); assert(t > 0); NEED_OP(t+3-1); + goto copy_match; +#endif + } + else if (t >= 32) + { + t &= 31; + if (t == 0) + { + NEED_IP(1); + while (*ip == 0) + { + t += 255; + ip++; + NEED_IP(1); + } + t += 31 + *ip++; + } +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off = 1 + (ip[0] << 6) + (ip[1] >> 2); + last_m_off = m_off; +#else + m_off = 1 + (ip[0] >> 2) + (ip[1] << 6); +#endif +#else +#if defined(LZO1Z) + { + lzo_uint off = 1 + (ip[0] << 6) + (ip[1] >> 2); + m_pos = op - off; + last_m_off = off; + } +#elif defined(LZO_UNALIGNED_OK_2) && defined(LZO_ABI_LITTLE_ENDIAN) + m_pos = op - 1; + m_pos -= (* (const lzo_ushortp) ip) >> 2; +#else + m_pos = op - 1; + m_pos -= (ip[0] >> 2) + (ip[1] << 6); +#endif +#endif + ip += 2; + } + else if (t >= 16) + { +#if defined(COPY_DICT) + m_off = (t & 8) << 11; +#else + m_pos = op; + m_pos -= (t & 8) << 11; +#endif + t &= 7; + if (t == 0) + { + NEED_IP(1); + while (*ip == 0) + { + t += 255; + ip++; + NEED_IP(1); + } + t += 7 + *ip++; + } +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off += (ip[0] << 6) + (ip[1] >> 2); +#else + m_off += (ip[0] >> 2) + (ip[1] << 6); +#endif + ip += 2; + if (m_off == 0) + goto eof_found; + m_off += 0x4000; +#if defined(LZO1Z) + last_m_off = m_off; +#endif +#else +#if defined(LZO1Z) + m_pos -= (ip[0] << 6) + (ip[1] >> 2); +#elif defined(LZO_UNALIGNED_OK_2) && defined(LZO_ABI_LITTLE_ENDIAN) + m_pos -= (* (const lzo_ushortp) ip) >> 2; +#else + m_pos -= (ip[0] >> 2) + (ip[1] << 6); +#endif + ip += 2; + if (m_pos == op) + goto eof_found; + m_pos -= 0x4000; +#if defined(LZO1Z) + last_m_off = pd((const lzo_bytep)op, m_pos); +#endif +#endif + } + else + { +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off = 1 + (t << 6) + (*ip++ >> 2); + last_m_off = m_off; +#else + m_off = 1 + (t >> 2) + (*ip++ << 2); +#endif + NEED_OP(2); + t = 2; COPY_DICT(t,m_off) +#else +#if defined(LZO1Z) + t = 1 + (t << 6) + (*ip++ >> 2); + m_pos = op - t; + last_m_off = t; +#else + m_pos = op - 1; + m_pos -= t >> 2; + m_pos -= *ip++ << 2; +#endif + TEST_LB(m_pos); NEED_OP(2); + *op++ = *m_pos++; *op++ = *m_pos; +#endif + goto match_done; + } + +#if defined(COPY_DICT) + + NEED_OP(t+3-1); + t += 3-1; COPY_DICT(t,m_off) + +#else + + TEST_LB(m_pos); assert(t > 0); NEED_OP(t+3-1); +#if defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4) +#if !defined(LZO_UNALIGNED_OK_4) + if (t >= 2 * 4 - (3 - 1) && PTR_ALIGNED2_4(op,m_pos)) + { + assert((op - m_pos) >= 4); +#else + if (t >= 2 * 4 - (3 - 1) && (op - m_pos) >= 4) + { +#endif + COPY4(op,m_pos); + op += 4; m_pos += 4; t -= 4 - (3 - 1); + do { + COPY4(op,m_pos); + op += 4; m_pos += 4; t -= 4; + } while (t >= 4); + if (t > 0) do *op++ = *m_pos++; while (--t > 0); + } + else +#endif + { +copy_match: + *op++ = *m_pos++; *op++ = *m_pos++; + do *op++ = *m_pos++; while (--t > 0); + } + +#endif + +match_done: +#if defined(LZO1Z) + t = ip[-1] & 3; +#else + t = ip[-2] & 3; +#endif + if (t == 0) + break; + +match_next: + assert(t > 0); assert(t < 4); NEED_OP(t); NEED_IP(t+1); +#if 0 + do *op++ = *ip++; while (--t > 0); +#else + *op++ = *ip++; + if (t > 1) { *op++ = *ip++; if (t > 2) { *op++ = *ip++; } } +#endif + t = *ip++; + } while (TEST_IP && TEST_OP); + } + +#if defined(HAVE_TEST_IP) || defined(HAVE_TEST_OP) + *out_len = pd(op, out); + return LZO_E_EOF_NOT_FOUND; +#endif + +eof_found: + assert(t == 1); + *out_len = pd(op, out); + return (ip == ip_end ? LZO_E_OK : + (ip < ip_end ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN)); + +#if defined(HAVE_NEED_IP) +input_overrun: + *out_len = pd(op, out); + return LZO_E_INPUT_OVERRUN; +#endif + +#if defined(HAVE_NEED_OP) +output_overrun: + *out_len = pd(op, out); + return LZO_E_OUTPUT_OVERRUN; +#endif + +#if defined(LZO_TEST_OVERRUN_LOOKBEHIND) +lookbehind_overrun: + *out_len = pd(op, out); + return LZO_E_LOOKBEHIND_OVERRUN; +#endif +} + +#endif + +/***** End of minilzo.c *****/ + diff --git a/minilzo.h b/minilzo.h new file mode 100644 index 0000000..0aff50e --- /dev/null +++ b/minilzo.h @@ -0,0 +1,106 @@ +/* minilzo.h -- mini subset of the LZO real-time data compression library + + This file is part of the LZO real-time data compression library. + + Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer + All Rights Reserved. + + The LZO library is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + The LZO 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with the LZO library; see the file COPYING. + If not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + Markus F.X.J. Oberhumer + + http://www.oberhumer.com/opensource/lzo/ + */ + +/* + * NOTE: + * the full LZO package can be found at + * http://www.oberhumer.com/opensource/lzo/ + */ + + +#ifndef __MINILZO_H +#define __MINILZO_H + +#define MINILZO_VERSION 0x2030 + +#ifdef __LZOCONF_H +# error "you cannot use both LZO and miniLZO" +#endif + +#undef LZO_HAVE_CONFIG_H +#include "lzoconf.h" + +#if !defined(LZO_VERSION) || (LZO_VERSION != MINILZO_VERSION) +# error "version mismatch in header files" +#endif + + +#ifdef __cplusplus +extern "C" { +#endif + + +/*********************************************************************** +// +************************************************************************/ + +/* Memory required for the wrkmem parameter. + * When the required size is 0, you can also pass a NULL pointer. + */ + +#define LZO1X_MEM_COMPRESS LZO1X_1_MEM_COMPRESS +#define LZO1X_1_MEM_COMPRESS ((lzo_uint32) (16384L * lzo_sizeof_dict_t)) +#define LZO1X_MEM_DECOMPRESS (0) + + +/* compression */ +LZO_EXTERN(int) +lzo1x_1_compress ( const lzo_bytep src, lzo_uint src_len, + lzo_bytep dst, lzo_uintp dst_len, + lzo_voidp wrkmem ); + +/* decompression */ +LZO_EXTERN(int) +lzo1x_decompress ( const lzo_bytep src, lzo_uint src_len, + lzo_bytep dst, lzo_uintp dst_len, + lzo_voidp wrkmem /* NOT USED */ ); + +/* safe decompression with overrun testing */ +LZO_EXTERN(int) +lzo1x_decompress_safe ( const lzo_bytep src, lzo_uint src_len, + lzo_bytep dst, lzo_uintp dst_len, + lzo_voidp wrkmem /* NOT USED */ ); + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* already included */ + diff --git a/n2n.c b/n2n.c new file mode 100644 index 0000000..af221ea --- /dev/null +++ b/n2n.c @@ -0,0 +1,892 @@ +/* + * (C) 2007-08 - Luca Deri + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see + * + * Code contributions courtesy of: + * Richard Andrews + * Massimo Torquati + * + */ + +#include "n2n.h" + +#include "minilzo.h" + +#include + +#if defined(DEBUG) +# define PURGE_REGISTRATION_FREQUENCY 60 +# define REGISTRATION_TIMEOUT 120 +#else /* #if defined(DEBUG) */ +# define PURGE_REGISTRATION_FREQUENCY 60 +# define REGISTRATION_TIMEOUT (60*5) +#endif /* #if defined(DEBUG) */ + + +char broadcast_addr[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; +char multicast_addr[6] = { 0x01, 0x00, 0x05, 0x00, 0x00, 0x00 }; /* First 3 bytes are meaningful */ + +/* ************************************** */ + +static void print_header( const char * msg, const struct n2n_packet_header * hdr ) +{ + ipstr_t buf; + ipstr_t buf2; + + traceEvent(TRACE_INFO, "%s hdr: public_ip=(%d)%s:%d, private_ip=(%d)%s:%d", msg, + hdr->public_ip.family, + intoa(ntohl(hdr->public_ip.addr_type.v4_addr), buf, sizeof(buf)), + ntohs(hdr->public_ip.port), + hdr->private_ip.family, + intoa(ntohl(hdr->private_ip.addr_type.v4_addr), buf2, sizeof(buf2)), + ntohs(hdr->private_ip.port) + ); +} + +/* *********************************************** */ + +extern void sockaddr_in2peer_addr(struct sockaddr_in *in, struct peer_addr *out) { + out->family = (u_int8_t)in->sin_family; + out->port = in->sin_port; + out->addr_type.v4_addr = in->sin_addr.s_addr; +} + +/* *********************************************** */ + +extern void peer_addr2sockaddr_in(const struct peer_addr *in, struct sockaddr_in *out) { + out->sin_family = in->family; + out->sin_port = in->port; + out->sin_addr.s_addr = in->addr_type.v4_addr; +} + +/* ************************************** */ + +static +int marshall_peer_addr( u_int8_t * buf, const struct peer_addr * s ) +{ + memcpy( buf, s, sizeof(struct peer_addr)); + buf += sizeof(struct peer_addr); + + return sizeof(struct peer_addr); /* bytes written */ +} + +/* ************************************** */ + +static +int marshall_uint32( u_int8_t * buf, u_int32_t val ) +{ + u_int32_t * nu32 = (u_int32_t *)buf; + *nu32 = htonl(val); + + return 4; +} + +/* ************************************** */ + +int marshall_n2n_packet_header( u_int8_t * buf, const struct n2n_packet_header * hdr ) +{ + u_int8_t * bufStart = buf; + + print_header( "Marshalling ", hdr ); + + *buf = hdr->version; + ++buf; + + *buf = hdr->msg_type; + ++buf; + + *buf = hdr->ttl; + ++buf; + + *buf = hdr->sent_by_supernode; + ++buf; + + memcpy( buf, hdr->community_name, COMMUNITY_LEN ); + buf += COMMUNITY_LEN; + + memcpy( buf, hdr->src_mac, 6 ); + buf += 6; + + memcpy( buf, hdr->dst_mac, 6 ); + buf += 6; + + buf += marshall_peer_addr( buf, &(hdr->public_ip) ); + buf += marshall_peer_addr( buf, &(hdr->private_ip) ); + + *buf = (hdr->pkt_type & 0xff); + ++buf; + + buf += marshall_uint32( buf, hdr->sequence_id ); + buf += marshall_uint32( buf, hdr->crc ); + + return (buf - bufStart); +} + +/* ************************************** */ + +static +int unmarshall_peer_addr( struct peer_addr * s, + const u_int8_t * buf ) +{ + memcpy(s, buf, sizeof(struct peer_addr)); + buf += sizeof(struct peer_addr); + return (sizeof(struct peer_addr)); /* bytes written */ +} + +/* ************************************** */ + +static +int unmarshall_uint32( u_int32_t * val, const u_int8_t * buf ) +{ + u_int32_t * nu32 = (u_int32_t *)buf; + *val = ntohl(*nu32); + + return 4; +} + +/* ************************************** */ + +int unmarshall_n2n_packet_header( struct n2n_packet_header * hdr, const u_int8_t * buf ) +{ + const u_int8_t * bufStart = buf; + + hdr->version = *buf; + ++buf; + + hdr->msg_type = *buf; + ++buf; + + hdr->ttl = *buf; + ++buf; + + hdr->sent_by_supernode = *buf; + ++buf; + + memcpy( hdr->community_name, buf, COMMUNITY_LEN ); + buf += COMMUNITY_LEN; + + memcpy( hdr->src_mac, buf, 6 ); + buf += 6; + + memcpy( hdr->dst_mac, buf, 6 ); + buf += 6; + + buf += unmarshall_peer_addr( &(hdr->public_ip), buf ); + buf += unmarshall_peer_addr( &(hdr->private_ip), buf ); + + hdr->pkt_type = (*buf & 0xff); /* Make sure only 8 bits are copied. */ + ++buf; + + buf += unmarshall_uint32( &(hdr->sequence_id), buf ); + buf += unmarshall_uint32( &(hdr->crc), buf ); + + print_header( "Unmarshalled ", hdr ); + + return (buf - bufStart); +} + +/* ************************************** */ + +SOCKET open_socket(int local_port, int udp_sock, int server_mode) { + SOCKET sock_fd; + struct sockaddr_in local_address; + int sockopt = 1; + + if((sock_fd = socket(PF_INET, udp_sock ? SOCK_DGRAM : SOCK_STREAM, 0)) < 0) { + traceEvent(TRACE_ERROR, "Unable to create socket [%s][%d]\n", + strerror(errno), sock_fd); + return(-1); + } + +#ifndef WIN32 + /* fcntl(sock_fd, F_SETFL, O_NONBLOCK); */ +#endif + + setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, (char *)&sockopt, sizeof(sockopt)); + + memset(&local_address, 0, sizeof(local_address)); + local_address.sin_family = AF_INET; + local_address.sin_port = htons(local_port); + local_address.sin_addr.s_addr = INADDR_ANY; + if(bind(sock_fd, (struct sockaddr*) &local_address, sizeof(local_address)) == -1) { + traceEvent(TRACE_ERROR, "Bind error [%s]\n", strerror(errno)); + return(-1); + } + + if((!udp_sock) && server_mode) { + if(listen(sock_fd, 255) == -1) { + traceEvent(TRACE_ERROR, "Listen error [%s]\n", strerror(errno)); + return(-1); + } + } + + return(sock_fd); +} + +/* ************************************** */ + +int connect_socket(int sock_fd, struct peer_addr* _dest) { + char *http_header; + int len, rc; + struct sockaddr_in dest; + + peer_addr2sockaddr_in(_dest, &dest); + + /* FIX: add IPv6 support */ + rc = connect(sock_fd, (struct sockaddr*)&dest, sizeof(struct sockaddr_in)); + + if(rc == -1) { + traceEvent(TRACE_WARNING, "connect() error [%s]\n", strerror(errno)); + return(-1); + } + + /* Send dummy http header */ + http_header = "GET / HTTP/1.0\r\n\r\n"; + len = strlen(http_header); + rc = send(sock_fd, http_header, len, 0); + + return((rc == len) ? 0 : -1); +} + + +/* *********************************************** */ + +void send_packet(n2n_sock_info_t * sinfo, + char *packet, size_t *packet_len, + const struct peer_addr *remote_peer, u_int8_t compress_data) { + int data_sent_len; + + data_sent_len = unreliable_sendto(sinfo, + packet, packet_len, remote_peer, compress_data); + + if(data_sent_len != *packet_len) + traceEvent(TRACE_WARNING, + "sendto() [sent=%d][attempted_to_send=%d] [%s]\n", + data_sent_len, *packet_len, strerror(errno)); +} + +/* *********************************************** */ + +int traceLevel = 2 /* NORMAL */; +int useSyslog = 0, syslog_opened = 0; + +#define N2N_TRACE_DATESIZE 32 +void traceEvent(int eventTraceLevel, char* file, int line, char * format, ...) { + va_list va_ap; + + if(eventTraceLevel <= traceLevel) { + char buf[2048]; + char out_buf[640]; + char theDate[N2N_TRACE_DATESIZE]; + char *extra_msg = ""; + time_t theTime = time(NULL); + + + /* We have two paths - one if we're logging, one if we aren't + * Note that the no-log case is those systems which don't support it (WIN32), + * those without the headers !defined(USE_SYSLOG) + * those where it's parametrically off... + */ + + memset(buf, 0, sizeof(buf)); + strftime(theDate, N2N_TRACE_DATESIZE, "%d/%b/%Y %H:%M:%S", localtime(&theTime)); + + va_start (va_ap, format); + vsnprintf(buf, sizeof(buf)-1, format, va_ap); + va_end(va_ap); + + if(eventTraceLevel == 0 /* TRACE_ERROR */) + extra_msg = "ERROR: "; + else if(eventTraceLevel == 1 /* TRACE_WARNING */) + extra_msg = "WARNING: "; + + while(buf[strlen(buf)-1] == '\n') buf[strlen(buf)-1] = '\0'; + +#ifndef WIN32 + if(useSyslog) { + if(!syslog_opened) { + openlog("n2n", LOG_PID, LOG_DAEMON); + syslog_opened = 1; + } + + snprintf(out_buf, sizeof(out_buf), "%s%s", extra_msg, buf); + syslog(LOG_INFO, out_buf); + } else { + snprintf(out_buf, sizeof(out_buf), "%s [%11s:%4d] %s%s", theDate, file, line, extra_msg, buf); + printf("%s\n", out_buf); + fflush(stdout); + } +#else + /* this is the WIN32 code */ + snprintf(out_buf, sizeof(out_buf), "%s [%11s:%4d] %s%s", theDate, file, line, extra_msg, buf); + printf("%s\n", out_buf); + fflush(stdout); +#endif + } + +} + +/* *********************************************** */ + +/* addr should be in network order. Things are so much simpler that way. */ +char* intoa(u_int32_t /* host order */ addr, char* buf, u_short buf_len) { + char *cp, *retStr; + u_int byte; + int n; + + cp = &buf[buf_len]; + *--cp = '\0'; + + n = 4; + do { + byte = addr & 0xff; + *--cp = byte % 10 + '0'; + byte /= 10; + if (byte > 0) { + *--cp = byte % 10 + '0'; + byte /= 10; + if (byte > 0) + *--cp = byte + '0'; + } + *--cp = '.'; + addr >>= 8; + } while (--n > 0); + + /* Convert the string to lowercase */ + retStr = (char*)(cp+1); + + return(retStr); +} + +/* *********************************************** */ + +char* macaddr_str(const char *mac, char *buf, int buf_len) { + snprintf(buf, buf_len, "%02X:%02X:%02X:%02X:%02X:%02X", + mac[0] & 0xFF, mac[1] & 0xFF, mac[2] & 0xFF, + mac[3] & 0xFF, mac[4] & 0xFF, mac[5] & 0xFF); + return(buf); +} + +/* *********************************************** */ + +void fill_standard_header_fields(n2n_sock_info_t * sinfo, + struct n2n_packet_header *hdr, char *src_mac) { + socklen_t len = sizeof(hdr->private_ip); + memset(hdr, 0, N2N_PKT_HDR_SIZE); + hdr->version = N2N_VERSION; + hdr->crc = 0; // FIX + if(src_mac != NULL) memcpy(hdr->src_mac, src_mac, 6); + getsockname(sinfo->sock, (struct sockaddr*)&hdr->private_ip, &len); + hdr->public_ip.family = AF_INET; +} + +/* *********************************************** */ + +void send_ack(n2n_sock_info_t * sinfo, + u_int16_t last_rcvd_seq_id, + struct n2n_packet_header *header, + struct peer_addr *remote_peer, + char *src_mac) { + + /* marshalling double-checked. */ + struct n2n_packet_header hdr; + u_int8_t pkt[ N2N_PKT_HDR_SIZE ]; + size_t len = sizeof(hdr); + size_t len2; + + fill_standard_header_fields(sinfo, &hdr, src_mac); + hdr.msg_type = MSG_TYPE_ACK_RESPONSE; + hdr.sequence_id = last_rcvd_seq_id; + memcpy(hdr.community_name, header->community_name, COMMUNITY_LEN); + + len2=marshall_n2n_packet_header( pkt, &hdr ); + assert( len2 == len ); + + send_packet(sinfo, (char*)pkt, &len, remote_peer, 1); +} + +/* *********************************************** */ + +u_int8_t is_multi_broadcast(char *dest_mac) { + return(((!memcmp(broadcast_addr, dest_mac, 6)) + || (!memcmp(multicast_addr, dest_mac, 3))) ? 1 : 0); +} + +/* *********************************************** */ + +/* http://www.faqs.org/rfcs/rfc908.html */ + +u_int receive_data(n2n_sock_info_t * sinfo, + char *packet, size_t packet_len, + struct peer_addr *from, u_int8_t *discarded_pkt, + char *tun_mac_addr, u_int8_t decompress_data, + struct n2n_packet_header *hdr) { + socklen_t fromlen = sizeof(struct sockaddr_in); + int len; + char *payload, *pkt_type; + macstr_t src_mac_buf; + macstr_t dst_mac_buf; + ipstr_t ip_buf; + ipstr_t from_ip_buf; + + if(sinfo->is_udp_socket) { + struct sockaddr_in _from; + len = recvfrom(sinfo->sock, packet, packet_len, 0, (struct sockaddr*)&_from, &fromlen); + sockaddr_in2peer_addr(&_from, from); + } else { + len = recv(sinfo->sock, packet, 4, 0); + if(len == 4) { + packet[4] = '\0'; + len = atoi(packet); + len = recv(sinfo->sock, packet, len, 0); + } else { + traceEvent(TRACE_WARNING, "Unable to receive n2n packet length"); + return(-1); + } + } + + unmarshall_n2n_packet_header(hdr, (u_int8_t *)packet); + + payload = &packet[N2N_PKT_HDR_SIZE]; + + if(len < 0) { +#ifdef WIN32 + if(WSAGetLastError() != WSAECONNRESET /* http://support.microsoft.com/kb/263823 */ ) { + traceEvent(TRACE_WARNING, "recvfrom returned %d [err=%d]", len, WSAGetLastError()); + } +#endif + return(0); + } else if(len > MIN_COMPRESSED_PKT_LEN) { + char decompressed[2048]; + int rc; + lzo_uint decompressed_len; + + if(decompress_data) { + rc = lzo1x_decompress((u_char*)&packet[N2N_PKT_HDR_SIZE], + len-N2N_PKT_HDR_SIZE, + (u_char*)decompressed, &decompressed_len, NULL); + + if(rc == LZO_E_OK) + traceEvent(TRACE_INFO, "%u bytes decompressed into %u", len, decompressed_len); + + if(packet_len > decompressed_len) { + memcpy(&packet[N2N_PKT_HDR_SIZE], decompressed, decompressed_len); + len = decompressed_len+N2N_PKT_HDR_SIZE; + } else { + traceEvent(TRACE_WARNING, "Uncompressed packet is too large [decompressed_len=%d]", + decompressed_len); + return(0); + } + } + + (*discarded_pkt) = 0; + + if(!hdr->sent_by_supernode) { + memcpy( &packet[offsetof(struct n2n_packet_header, public_ip)], from, sizeof(struct sockaddr_in) ); + } + + switch(hdr->pkt_type) { + case packet_unreliable_data: + pkt_type = "unreliable data"; + break; + case packet_reliable_data: + pkt_type = "reliable data"; + break; + case packet_ping: + pkt_type = "ping"; + break; + case packet_pong: + pkt_type = "pong"; + break; + default: + pkt_type = "???"; + } + + traceEvent(TRACE_INFO, "+++ Received %s packet [rcvd_from=%s:%d][msg_type=%s][seq_id=%d]", + pkt_type, + intoa(ntohl(from->addr_type.v4_addr), from_ip_buf, sizeof(from_ip_buf)), + ntohs(from->port), msg_type2str(hdr->msg_type), + hdr->sequence_id); + traceEvent(TRACE_INFO, " [src_mac=%s][dst_mac=%s][original_sender=%s:%d]", + macaddr_str(hdr->src_mac, src_mac_buf, sizeof(src_mac_buf)), + macaddr_str(hdr->dst_mac, dst_mac_buf, sizeof(dst_mac_buf)), + intoa(ntohl(hdr->public_ip.addr_type.v4_addr), ip_buf, sizeof(ip_buf)), + ntohs(hdr->public_ip.port)); + +#ifdef HANDLE_RETRANSMISSION + if((hdr->pkt_type == packet_reliable_data) + && (hdr->msg_type == MSG_TYPE_PACKET)) { + (*discarded_pkt) = handle_ack(sock_fd, is_udp_socket, hdr, + &payload[6], payload, from, tun_mac_addr); + } else + (*discarded_pkt) = 0; +#endif + } else + traceEvent(TRACE_WARNING, "Receive error [%s] or pkt too short [len=%d]\n", + strerror(errno), len); + + return(len); +} + +/* *********************************************** */ + +#if 0 +static u_int32_t queue_packet(struct send_hash_entry *scan, + char *packet, + u_int16_t packet_len) { + struct packet_list *pkt = (struct packet_list*)malloc(sizeof(struct packet_list)); + + if(pkt == NULL) { + traceEvent(TRACE_ERROR, "Not enough memory!"); + return(0); + } + + if((pkt->packet = (char*)malloc(packet_len)) == NULL) { + traceEvent(TRACE_ERROR, "Not enough memory!"); + return(0); + } + + memcpy(pkt->packet, packet, packet_len); + pkt->packet_len = packet_len; + pkt->seq_id = scan->last_seq_id; + pkt->next = scan->unacked_packet_list; + scan->unacked_packet_list = pkt; + scan->num_unacked_pkts++; + return(pkt->seq_id); +} +#endif + +/* *********************************************** */ + +/* Work-memory needed for compression. Allocate memory in units + * of `lzo_align_t' (instead of `char') to make sure it is properly aligned. + */ + +#define HEAP_ALLOC(var,size) \ + lzo_align_t __LZO_MMODEL var [ ((size) + (sizeof(lzo_align_t) - 1)) / sizeof(lzo_align_t) ] + +static HEAP_ALLOC(wrkmem,LZO1X_1_MEM_COMPRESS); + +/* ******************************************************* */ + +u_int send_data(n2n_sock_info_t * sinfo, + char *packet, size_t *packet_len, + const struct peer_addr *to, u_int8_t compress_data) { + char compressed[1600]; + int rc; + lzo_uint compressed_len; + struct sockaddr_in destsock; + + if(*packet_len < N2N_PKT_HDR_SIZE) { + traceEvent(TRACE_WARNING, "The packet about to be sent is too short [len=%d]\n", *packet_len); + return(-1); + } + + memcpy(compressed, packet, N2N_PKT_HDR_SIZE); + + peer_addr2sockaddr_in(to, &destsock); + + if(compress_data) { + rc = lzo1x_1_compress((u_char*)&packet[N2N_PKT_HDR_SIZE], + *packet_len - N2N_PKT_HDR_SIZE, + (u_char*)&compressed[N2N_PKT_HDR_SIZE], + &compressed_len, wrkmem); + compressed_len += N2N_PKT_HDR_SIZE; + + traceEvent(TRACE_INFO, "%u bytes compressed into %u", *packet_len, compressed_len); + /* *packet_len = compressed_len; */ + + if(sinfo->is_udp_socket) { + rc = sendto(sinfo->sock, compressed, compressed_len, 0, + (struct sockaddr*)&destsock, sizeof(struct sockaddr_in)); + } else { + char send_len[5]; + + /* 4 bytes packet length */ + snprintf(send_len, sizeof(send_len), "%04d", (int)compressed_len); + if((rc = send(sinfo->sock, send_len, 4, 0)) != 4) + return(-1); + if((rc = send(sinfo->sock, compressed, compressed_len, 0)) != compressed_len) { + traceEvent(TRACE_WARNING, "send error [%d][%s]", + errno, strerror(errno)); + } + } + } else { + compressed_len = *packet_len; + if(sinfo->is_udp_socket) + rc = sendto(sinfo->sock, packet, compressed_len, 0, + (struct sockaddr*)&destsock, sizeof(struct sockaddr_in)); + else { + char send_len[5]; + + /* 4 bytes packet length */ + snprintf(send_len, sizeof(send_len), "%04d", (int)compressed_len); + if((rc = send(sinfo->sock, send_len, 4, 0)) != 4) + return(-1); + rc = send(sinfo->sock, compressed, compressed_len, 0); + } + + if(rc == -1) { + ipstr_t ip_buf; + + traceEvent(TRACE_WARNING, "sendto() failed while attempting to send data to %s:%d", + intoa(ntohl(to->addr_type.v4_addr), ip_buf, sizeof(ip_buf)), + ntohs(to->port)); + } + } + + if ( rc >= 0) { + traceEvent(TRACE_INFO, "### Tx N2N Msg -> network"); + } + + if(rc == compressed_len) + return(*packet_len); /* fake just to avoid warnings */ + else + return(rc); +} + +/* *********************************************** */ + +u_int reliable_sendto(n2n_sock_info_t * sinfo, + char *packet, size_t *packet_len, + const struct peer_addr *to, u_int8_t compress_data) { + /* char *payload = &packet[N2N_PKT_HDR_SIZE]; */ + struct n2n_packet_header hdr_storage; + struct n2n_packet_header *hdr = &hdr_storage; + macstr_t src_mac_buf; + macstr_t dst_mac_buf; + + /* REVISIT: efficiency of unmarshal + re-marshal just to change a couple of bits. */ + unmarshall_n2n_packet_header( hdr, (u_int8_t *)packet ); + + /* hdr->sequence_id = (hdr->msg_type == MSG_TYPE_PACKET) ? mac2sequence((u_char*)payload, packet, *packet_len) : 0; */ + hdr->sequence_id = 0; + hdr->pkt_type = packet_reliable_data; + + traceEvent(TRACE_INFO, "Sent reliable packet [msg_type=%s][seq_id=%d][src_mac=%s][dst_mac=%s]", + msg_type2str(hdr->msg_type), hdr->sequence_id, + macaddr_str(&packet[6], src_mac_buf, sizeof(src_mac_buf)), + macaddr_str(packet, dst_mac_buf, sizeof(dst_mac_buf))); + + marshall_n2n_packet_header( (u_int8_t *)packet, hdr ); + + return(send_data(sinfo, packet, packet_len, to, compress_data)); +} + +/* *********************************************** */ + +/* unreliable_sendto is passed a fully marshalled, packet. Its purpose is to set + * the unreliable flags but leave the rest of the packet untouched. */ +u_int unreliable_sendto(n2n_sock_info_t * sinfo, + char *packet, size_t *packet_len, + const struct peer_addr *to, u_int8_t compress_data) { + struct n2n_packet_header hdr_storage; + struct n2n_packet_header *hdr = &hdr_storage; + macstr_t src_mac_buf; + macstr_t dst_mac_buf; + + /* REVISIT: efficiency of unmarshal + re-marshal just to change a couple of bits. */ + unmarshall_n2n_packet_header( hdr, (u_int8_t *)packet ); + + hdr->sequence_id = 0; /* Unreliable messages have 0 as sequence number */ + hdr->pkt_type = packet_unreliable_data; + + traceEvent(TRACE_INFO, "Sent unreliable packet [msg_type=%s][seq_id=%d][src_mac=%s][dst_mac=%s]", + msg_type2str(hdr->msg_type), hdr->sequence_id, + macaddr_str(hdr->src_mac, src_mac_buf, sizeof(src_mac_buf)), + macaddr_str(hdr->dst_mac, dst_mac_buf, sizeof(dst_mac_buf))); + + marshall_n2n_packet_header( (u_int8_t *)packet, hdr ); + + return(send_data(sinfo, packet, packet_len, to, compress_data)); +} + +/* *********************************************** */ + +char* msg_type2str(u_short msg_type) { + switch(msg_type) { + case MSG_TYPE_REGISTER: return("MSG_TYPE_REGISTER"); + case MSG_TYPE_DEREGISTER: return("MSG_TYPE_DEREGISTER"); + case MSG_TYPE_PACKET: return("MSG_TYPE_PACKET"); + case MSG_TYPE_REGISTER_ACK: return("MSG_TYPE_REGISTER_ACK"); + case MSG_TYPE_ACK_RESPONSE: return("MSG_TYPE_ACK_RESPONSE"); + } + + return("???"); +} + +/* *********************************************** */ + +void hexdump(char *buf, u_int len) { + u_int i; + + for(i=0; i 0) && ((i % 16) == 0)) printf("\n"); + printf("%02X ", buf[i] & 0xFF); + } + + printf("\n"); +} + +/* *********************************************** */ + +void print_n2n_version() { + printf("Welcome to n2n v.%s for %s\n" + "Built on %s\n" + "Copyright 2007-08 - http://www.ntop.org\n\n", + version, osName, buildDate); +} + + + + +/** Find the peer entry in list with mac_addr equal to mac. + * + * Does not modify the list. + * + * @return NULL if not found; otherwise pointer to peer entry. + */ +struct peer_info * find_peer_by_mac( struct peer_info * list, const char * mac ) +{ + while(list != NULL) + { + if( 0 == memcmp(mac, list->mac_addr, 6) ) + { + return list; + } + list = list->next; + } + + return NULL; +} + + +/** Return the number of elements in the list. + * + */ +size_t peer_list_size( const struct peer_info * list ) +{ + size_t retval=0; + + while ( list ) + { + ++retval; + list = list->next; + } + + return retval; +} + +/** Add new to the head of list. If list is NULL; create it. + * + * The item new is added to the head of the list. New is modified during + * insertion. list takes ownership of new. + */ +void peer_list_add( struct peer_info * * list, + struct peer_info * new ) +{ + new->next = *list; + new->last_seen = time(NULL); + *list = new; +} + + +size_t purge_expired_registrations( struct peer_info ** peer_list ) { + static time_t last_purge = 0; + time_t now = time(NULL); + size_t num_reg = 0; + + if((now - last_purge) < PURGE_REGISTRATION_FREQUENCY) return 0; + + traceEvent(TRACE_INFO, "Purging old registrations"); + + num_reg = purge_peer_list( peer_list, now-REGISTRATION_TIMEOUT ); + + last_purge = now; + traceEvent(TRACE_INFO, "Remove %ld registrations", num_reg); + + return num_reg; +} + +/** Purge old items from the peer_list and return the number of items that were removed. */ +size_t purge_peer_list( struct peer_info ** peer_list, + time_t purge_before ) +{ + struct peer_info *scan; + struct peer_info *prev; + size_t retval=0; + + scan = *peer_list; + prev = NULL; + while(scan != NULL) + { + if(scan->last_seen < purge_before) + { + struct peer_info *next = scan->next; + + if(prev == NULL) + { + *peer_list = next; + } + else + { + prev->next = next; + } + + ++retval; + free(scan); + scan = next; + } + else + { + prev = scan; + scan = scan->next; + } + } + + return retval; +} + +static u_int8_t hex2byte( const char * s ) +{ + char tmp[3]; + tmp[0]=s[0]; + tmp[1]=s[1]; + tmp[2]=0; /* NULL term */ + + return((u_int8_t)strtol( s, NULL, 16 )); +} + +extern int str2mac( u_int8_t * outmac /* 6 bytes */, const char * s ) +{ + size_t i; + + /* break it down as one case for the first "HH", the 5 x through loop for + * each ":HH" where HH is a two hex nibbles in ASCII. */ + + *outmac=hex2byte(s); + ++outmac; + s+=2; /* don't skip colon yet - helps generalise loop. */ + + for (i=1; i<6; ++i ) + { + s+=1; + *outmac=hex2byte(s); + ++outmac; + s+=2; + } + + return 0; /* ok */ +} diff --git a/n2n.h b/n2n.h new file mode 100644 index 0000000..aaded83 --- /dev/null +++ b/n2n.h @@ -0,0 +1,290 @@ +/* + * (C) 2007-08 - Luca Deri + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see + * + * Code contributions courtesy of: + * Richard Andrews + * Babak Farrokhi [FreeBSD port] + * +*/ + +#ifndef _N2N_H_ +#define _N2N_H_ + +/* + tunctl -t tun0 + tunctl -t tun1 + ifconfig tun0 1.2.3.4 up + ifconfig tun1 1.2.3.5 up + ./edge -d tun0 -l 2000 -r 127.0.0.1:3000 -c hello + ./edge -d tun1 -l 3000 -r 127.0.0.1:2000 -c hello + + + tunctl -u UID -t tunX +*/ + +#if defined(__APPLE__) && defined(__MACH__) +#define _DARWIN_ +#endif + +#ifdef WIN32 +#include "win32/n2n_win32.h" +#endif + +#include +#include +#include + +#ifndef WIN32 +#include +#endif + +#include +#include +#include + +#ifndef WIN32 +#include +#include +#include +#include +#include + +#ifdef __linux__ +#include +#include +#endif + +#ifdef __FreeBSD__ +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define closesocket(a) close(a) +#endif + +#include +#ifdef WIN32 +#include "win32/getopt.h" +#else +#define _GNU_SOURCE +#include +#endif + +#include + +#ifdef WIN32 +#include "win32/wintap.h" +#endif + +#include "twofish.h" + +#ifndef WIN32 +typedef struct tuntap_dev { + int fd; + u_int8_t mac_addr[6]; + u_int32_t ip_addr, device_mask; + u_int mtu; +} tuntap_dev; + +#define SOCKET int +#endif /* #ifndef WIN32 */ + +#define QUICKLZ 1 +#define N2N_VERSION 1 + +#define MSG_TYPE_REGISTER 1 /* FIX invece di usare il sender del pacchetto scriverlo nel pacchetto stesso */ +#define MSG_TYPE_DEREGISTER 2 +#define MSG_TYPE_PACKET 3 +#define MSG_TYPE_REGISTER_ACK 4 +#define MSG_TYPE_ACK_RESPONSE 5 + +#define COMMUNITY_LEN 16 +#define MIN_COMPRESSED_PKT_LEN 32 + +/* Maximum enum value is 255 due to marshalling into 1 byte */ +enum packet_type { + packet_unreliable_data = 0, /* no ACK needed */ + packet_reliable_data, /* needs ACK */ + packet_ping, + packet_pong +}; + +/* All information is always in network byte-order */ +struct peer_addr { + u_int8_t family; + u_int16_t port; + union { + u_int8_t v6_addr[16]; + u_int32_t v4_addr; + } addr_type; +}; + +struct n2n_packet_header { + u_int8_t version, msg_type, ttl, sent_by_supernode; + char community_name[COMMUNITY_LEN], src_mac[6], dst_mac[6]; + struct peer_addr public_ip, private_ip; + enum packet_type pkt_type; + u_int32_t sequence_id; + u_int32_t crc; // FIX - It needs to be handled for detcting forged packets +}; + +int marshall_n2n_packet_header( u_int8_t * buf, const struct n2n_packet_header * hdr ); +int unmarshall_n2n_packet_header( struct n2n_packet_header * hdr, const u_int8_t * buf ); + +#define N2N_PKT_HDR_SIZE (sizeof(struct n2n_packet_header)) + + +/** Common type used to hold stringified IP addresses. */ +typedef char ipstr_t[32]; + +/** Common type used to hold stringified MAC addresses. */ +typedef char macstr_t[32]; + +struct n2n_sock_info +{ + int sock; + char is_udp_socket /*= 1*/; +}; + +typedef struct n2n_sock_info n2n_sock_info_t; + +struct peer_info { + char community_name[16], mac_addr[6]; + struct peer_addr public_ip, private_ip; + time_t last_seen; + struct peer_info *next; + /* socket */ + n2n_sock_info_t sinfo; +}; + +struct n2n_edge; /* defined in edge.c */ +typedef struct n2n_edge n2n_edge_t; + + +/* ************************************** */ + +#if defined(DEBUG) +#define SOCKET_TIMEOUT_INTERVAL_SECS 5 +#define REGISTER_FREQUENCY 20 /* sec */ +#else /* #if defined(DEBUG) */ +#define SOCKET_TIMEOUT_INTERVAL_SECS 10 +#define REGISTER_FREQUENCY 60 /* sec */ +#endif /* #if defined(DEBUG) */ + +#define TRACE_ERROR 0, __FILE__, __LINE__ +#define TRACE_WARNING 1, __FILE__, __LINE__ +#define TRACE_NORMAL 2, __FILE__, __LINE__ +#define TRACE_INFO 3, __FILE__, __LINE__ + +/* ************************************** */ + +#define SUPERNODE_IP "127.0.0.1" +#define SUPERNODE_PORT 1234 + +/* ************************************** */ + +#ifndef max +#define max(a, b) ((a < b) ? b : a) +#endif + +#ifndef min +#define min(a, b) ((a > b) ? b : a) +#endif + +/* ************************************** */ + +/* Variables */ +// extern TWOFISH *tf; +extern int traceLevel; +extern char broadcast_addr[6]; +extern char multicast_addr[6]; + +/* Functions */ +extern void sockaddr_in2peer_addr(struct sockaddr_in *in, struct peer_addr *out); +extern void peer_addr2sockaddr_in(const struct peer_addr *in, struct sockaddr_in *out); +// extern int init_n2n(u_int8_t *encrypt_pwd, u_int32_t encrypt_pwd_len ); +// extern void term_n2n(); +extern void send_ack(n2n_sock_info_t * sinfo, + u_int16_t last_rcvd_seq_id, + struct n2n_packet_header *header, + struct peer_addr *remote_peer, + char *src_mac); + +extern void traceEvent(int eventTraceLevel, char* file, int line, char * format, ...); +extern int tuntap_open(tuntap_dev *device, char *dev, char *device_ip, char *device_mask, const char * device_mac ); +extern int tuntap_read(struct tuntap_dev *tuntap, unsigned char *buf, int len); +extern int tuntap_write(struct tuntap_dev *tuntap, unsigned char *buf, int len); +extern void tuntap_close(struct tuntap_dev *tuntap); + +extern SOCKET open_socket(int local_port, int udp_sock, int server_mode); +extern int connect_socket(int sock_fd, struct peer_addr* dest); + +extern void send_packet(n2n_sock_info_t * sinfo, + char *packet, size_t *packet_len, + const struct peer_addr *remote_peer, + u_int8_t compress_data); +extern char* intoa(u_int32_t addr, char* buf, u_short buf_len); +extern char* macaddr_str(const char *mac, char *buf, int buf_len); +extern int str2mac( u_int8_t * outmac /* 6 bytes */, const char * s ); +extern void fill_standard_header_fields(n2n_sock_info_t * eee, + struct n2n_packet_header *hdr, + char *src_mac); + +extern u_int receive_data(n2n_sock_info_t * sinfo, + char *packet, size_t packet_len, + struct peer_addr *from, u_int8_t *discarded_pkt, + char *tun_mac_addr, u_int8_t decompress_data, + struct n2n_packet_header *hdr); +extern u_int reliable_sendto(n2n_sock_info_t * sinfo, + char *packet, size_t *packet_len, + const struct peer_addr *from, u_int8_t compress_data); +extern u_int unreliable_sendto(n2n_sock_info_t * sinfo, + char *packet, size_t *packet_len, + const struct peer_addr *from, u_int8_t compress_data); +extern u_int send_data(n2n_sock_info_t * sinfo, + char *packet, size_t *packet_len, + const struct peer_addr *to, u_int8_t compress_data); +extern u_int8_t is_multi_broadcast(char *dest_mac); +extern char* msg_type2str(u_short msg_type); +extern void hexdump(char *buf, u_int len); + +void print_n2n_version(); + + +/* Operations on peer_info lists. */ +struct peer_info * find_peer_by_mac( struct peer_info * list, + const char * mac ); +void peer_list_add( struct peer_info * * list, + struct peer_info * new ); +size_t peer_list_size( const struct peer_info * list ); +size_t purge_peer_list( struct peer_info ** peer_list, + time_t purge_before ); +size_t purge_expired_registrations( struct peer_info ** peer_list ); + +/* version.c */ +extern char *version, *osName, *buildDate; + +#endif /* _N2N_H_ */ diff --git a/n2n.spec b/n2n.spec new file mode 100644 index 0000000..8eede44 --- /dev/null +++ b/n2n.spec @@ -0,0 +1,47 @@ +Summary: N2N peer-to-peer virtual private network system. +Name: n2n +Version: 1.2 +Release: 1 +License: GPLv3 +Vendor: ntop.org +Group: None +URL: http://www.ntop.org/n2n +Source0: %{name}-%{version}.tar.gz +BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root + +%description +N2N is a peer-to-peer virtual private network system. N2N uses the universal +TUNTAP interface to create TAP network interfaces to an encrypted virtual +LAN. Members of a community share a common encryption key which allows echange +of data. The supernode is used for peer discovery and initial packet relay +before direct peer-to-peer exchange is established. +Once direct packet exchange is established, the supernode is not required. + +%prep + +%setup -q + +echo -e "\n *** Building ${RPM_PACKAGE_NAME}-${RPM_PACKAGE_VERSION}-${RPM_PACKAGE_RELEASE} ***\n" + +%build +make + +%install +make PREFIX=${RPM_BUILD_ROOT}/usr install + +%clean +rm -rf $RPM_BUILD_ROOT + + +%files +%defattr(-,root,root,-) + /usr/bin/supernode + /usr/sbin/edge +%doc /usr/share/man/man1/supernode.1.gz +%doc /usr/share/man/man8/edge.8.gz + + +%changelog +* Sat May 3 2008 Richard Andrews - +- Initial build. + diff --git a/openwrt/kamikaze/Makefile b/openwrt/kamikaze/Makefile new file mode 100644 index 0000000..ddcc7c1 --- /dev/null +++ b/openwrt/kamikaze/Makefile @@ -0,0 +1,55 @@ +# +# Copyright (C) 2008 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. + + +include $(TOPDIR)/rules.mk + +PKG_BRANCH:=trunk +PKG_SOURCE_URL:=https://svn.ntop.org/svn/ntop/trunk/n2n +PKG_REV:=$(shell LC_ALL=C svn info ${PKG_SOURCE_URL} | sed -ne's/^Last Changed Rev: //p') + +PKG_NAME:=n2n +PKG_VERSION:=svn$(PKG_REV) +PKG_RELEASE:=1 + +PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION) +PKG_SOURCE:=$(PKG_SOURCE_SUBDIR).tar.gz +PKG_SOURCE_PROTO:=svn +PKG_SOURCE_VERSION:=$(PKG_REV) + +PKG_BUILD_DEPENDS:= + +PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION) +PKG_INSTALL_DIR:=$(PKG_BUILD_DIR) + + + +include $(INCLUDE_DIR)/package.mk + +define Package/n2n + SECTION:=net + CATEGORY:=Network + TITLE:=VPN tunneling daemon + URL:=http://www.ntop.org/n2n/ + SUBMENU:=VPN + DEPENDS:=libpthread +endef + + +define Build/Configure +endef + +define Build/Compile + $(MAKE) CC="$(TARGET_CC)" -C $(PKG_BUILD_DIR) +endef + + +define Package/n2n/install + $(INSTALL_DIR) $(1)/usr/sbin + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/edge $(1)/usr/sbin/ + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/supernode $(1)/usr/sbin/ +endef + +$(eval $(call BuildPackage,n2n)) diff --git a/scripts/mk_SRPM.sh b/scripts/mk_SRPM.sh new file mode 100755 index 0000000..2b1b374 --- /dev/null +++ b/scripts/mk_SRPM.sh @@ -0,0 +1,30 @@ +#!/bin/sh + +# This script makes a SRPM - a source RPM file which can be built into the +# appropriate distro specific RPM for any platform. +# +# To build the binary package: +# rpm -i n2n-.src.rpm +# rpmbuild -bb n2n.spec +# +# Look for the "Wrote:" line to see where the final RPM is. +# +# To run this script cd to the n2n directory and run it as follows +# scripts/mk_SRPMS.sh +# + +set -e + +set -x + +BASE=`pwd` + +TARFILE=`${BASE}/scripts/mk_tar.sh` + +test -f ${TARFILE} + +echo "Building SRPM" +# -ts means build source RPM from tarfile +rpmbuild -ts ${TARFILE} + +echo "Done" diff --git a/scripts/mk_deb.sh b/scripts/mk_deb.sh new file mode 100755 index 0000000..42d8691 --- /dev/null +++ b/scripts/mk_deb.sh @@ -0,0 +1,46 @@ +#!/bin/bash + +# This script makes a SRPM - a source RPM file which can be built into the +# appropriate distro specific RPM for any platform. +# +# To build the binary package: +# rpm -i n2n-.src.rpm +# rpmbuild -bb n2n.spec +# +# Look for the "Wrote:" line to see where the final RPM is. +# +# To run this script cd to the n2n directory and run it as follows +# scripts/mk_SRPMS.sh +# + +set -e + +set -x + +BASE=`pwd` + +TARFILE=`${BASE}/scripts/mk_tar.sh` +TEMPDIR="build_deb" + +test -f ${TARFILE} + +echo "Building .deb" + +if [ -d ${TEMPDIR} ]; then + echo "Removing ${TEMPDIR} directory" + rm -rf ${TEMPDIR} >&2 +fi + +mkdir ${TEMPDIR} + +pushd ${TEMPDIR} + +tar xzf ${TARFILE} #At original location + +cd n2n* + +dpkg-buildpackage -rfakeroot + +popd + +echo "Done" diff --git a/scripts/mk_tar.sh b/scripts/mk_tar.sh new file mode 100755 index 0000000..347191b --- /dev/null +++ b/scripts/mk_tar.sh @@ -0,0 +1,105 @@ +#!/bin/bash + +# This script makes a SRPM - a source RPM file which can be built into the +# appropriate distro specific RPM for any platform. +# +# To build the binary package: +# rpm -i n2n-.src.rpm +# rpmbuild -bb n2n.spec +# +# Look for the "Wrote:" line to see where the final RPM is. +# +# To run this script cd to the n2n directory and run it as follows +# scripts/mk_SRPMS.sh +# + +set -e + +function exit_fail() +{ + echo "$1" + exit 1 +} + +PACKAGE="n2n" +PKG_VERSION="1.2" +PKG_AND_VERSION="${PACKAGE}-${PKG_VERSION}" + +TEMPDIR="tmp" + +SOURCE_MANIFEST=" +README +edge.c +lzoconf.h +lzodefs.h +Makefile +minilzo.c +minilzo.h +n2n.c +n2n.h +n2n.spec +supernode.c +tuntap_linux.c +tuntap_freebsd.c +tuntap_osx.c +twofish.c +twofish.h +edge.8 +supernode.1 +debian/changelog +debian/compat +debian/control +debian/copyright +debian/files +debian/n2n.dirs +debian/n2n.docs +debian/n2n.install +debian/n2n.manpages +debian/README.Debian +debian/rules +" + +BASE=`pwd` + +for F in ${SOURCE_MANIFEST}; do + test -e $F || exit_fail "Wrong directory. Please execute from n2n directory."; >&2 +done + +echo "Found critical files. Proceeding." >&2 + +if [ -d ${TEMPDIR} ]; then + echo "Removing ${TEMPDIR} directory" + rm -rf ${TEMPDIR} >&2 +fi + +mkdir ${TEMPDIR} >&2 + +pushd ${TEMPDIR} >&2 + +echo "Creating staging directory ${PWD}/${PKG_AND_VERSION}" >&2 + +if [ -d ${PKG_AND_VERSION} ] ; then + echo "Removing ${PKG_AND_VERSION} directory" + rm -rf ${PKG_AND_VERSION} >&2 +fi + +mkdir ${PKG_AND_VERSION} + +pushd ${BASE} >&2 + +echo "Copying in files" >&2 +for F in ${SOURCE_MANIFEST}; do + cp --parents -a $F ${TEMPDIR}/${PKG_AND_VERSION}/ +done + +popd >&2 + +TARFILE="${PKG_AND_VERSION}.tar.gz" +echo "Creating ${TARFILE}" >&2 +tar czf ${BASE}/${TARFILE} ${PKG_AND_VERSION} + +popd >&2 + +rm -rf ${TEMPDIR} >&2 + +echo ${BASE}/${TARFILE} diff --git a/supernode.1 b/supernode.1 new file mode 100644 index 0000000..808f803 --- /dev/null +++ b/supernode.1 @@ -0,0 +1,32 @@ +.TH supernode 1 "May 3, 2008" "revision 3472" "USER COMMANDS" +.SH NAME +supernode \- n2n supernode daemon +.SH SYNOPSIS +.B supernode \-l [\-v] +.SH DESCRIPTION +N2N is a peer-to-peer VPN system. Supernode is a node introduction registry, +broadcast conduit and packet relay node for the n2n system. On startup supernode +begins listening on the specified UDP port for node registrations, and other +packets to route. The supernode can service any number of communities and routes +packets only between members of the same community. The supernode does not hold +the community encryption key and so cannot snoop or inject packets into the +community. +.PP +All logging goes to stdout. +.SH OPTIONS +.TP +\-l +listen on the given UDP port +\-v +use verbose logging +.SH EXAMPLES +.TP +.B supernode -l 7654 -v +Start supernode listening on UDP port 7654 with verbose output. +.PP +.SH EXIT STATUS +edge is a daemon and any exit is an error +.SH AUTHOR +Luca Deri ( deri (at) ntop.org ), Richard Andrews ( andrews (at) ntop.org ), Don Bindner +.SH SEE ALSO +ifconfig(1) edge(1) diff --git a/supernode.c b/supernode.c new file mode 100644 index 0000000..4031472 --- /dev/null +++ b/supernode.c @@ -0,0 +1,525 @@ +/* + * (C) 2007-08 - Luca Deri + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see + * + * Code contributions courtesy of: + * Richard Andrews + * +*/ + +#include "n2n.h" + +struct tx_stats +{ + size_t pkts; + size_t errors; +}; + + +/* *********************************************** */ + +static void help() { + print_n2n_version(); + printf("supernode -l [-v] [-h]\n"); + exit(0); +} + +/* *********************************************** */ + +static struct peer_info *known_peers = NULL; +static struct tx_stats supernode_stats = {0,0}; + +/* *********************************************** */ + +/** Turn a REGISTER request around and send a REGISTER_ACK packet back to the + * sender. + * + * This needs to be done for all incoming REGISTER packets to keep firewalls + * open + */ +static void send_register_ack( n2n_sock_info_t * sinfo, + const struct peer_addr *destination_peer, + const struct n2n_packet_header * reqhdr ) +{ + struct n2n_packet_header hdr; + u_int8_t pkt[N2N_PKT_HDR_SIZE]; + size_t len = sizeof(hdr); + + fill_standard_header_fields(sinfo, &hdr, NULL /* zero src MAC */ ); + hdr.sent_by_supernode = 1; + hdr.msg_type = MSG_TYPE_REGISTER_ACK; + memcpy( hdr.community_name, reqhdr->community_name, COMMUNITY_LEN); + memcpy( hdr.dst_mac, reqhdr->src_mac, 6); /* turn it around */ + /* leave IP sockets unfilled. */ + + marshall_n2n_packet_header( pkt, &hdr ); + send_packet(sinfo, (char *)pkt, &len, destination_peer, 1); +} + +static void register_peer(struct n2n_packet_header *hdr, + struct peer_addr *sender, + n2n_sock_info_t * sinfo) { + struct peer_info *scan = known_peers; + ipstr_t buf, buf1; + macstr_t mac_buf; + + send_register_ack( sinfo, sender, hdr ); /* keep firewalls open */ + + while(scan != NULL) { + if((strcmp(scan->community_name, hdr->community_name) == 0) + && (memcmp(&scan->mac_addr, hdr->src_mac, 6) == 0)) { + + scan->last_seen = time(NULL); + if ( ( 0 != memcmp(&scan->public_ip, sender, sizeof(struct peer_addr)) ) || + ( 0 != memcmp(&scan->private_ip, &hdr->private_ip, sizeof(struct peer_addr)) ) ) + { + /* Something is actually different. */ + memcpy(&scan->public_ip, sender, sizeof(struct peer_addr)); + memcpy(&scan->private_ip, &hdr->private_ip, sizeof(struct peer_addr)); + + /* Overwrite existing peer */ + traceEvent(TRACE_NORMAL, "Re-registered node [public_ip=(%d)%s:%d][private_ip=%s:%d][mac=%s][community=%s]", + scan->public_ip.family, + intoa(ntohl(scan->public_ip.addr_type.v4_addr), buf, sizeof(buf)), + ntohs(scan->public_ip.port), + intoa(ntohl(scan->private_ip.addr_type.v4_addr), buf1, sizeof(buf1)), + ntohs(scan->private_ip.port), + macaddr_str(scan->mac_addr, mac_buf, sizeof(mac_buf)), + scan->community_name); + } + + return; /* Found the registration entry so stop. */ + } + + scan = scan->next; + } + + /* FIX mettere un limite alla lista dei peer */ + + scan = (struct peer_info*)calloc(1, sizeof(struct peer_info)); + memcpy(scan->community_name, hdr->community_name, COMMUNITY_LEN); + memcpy(&scan->public_ip, sender, sizeof(struct peer_addr)); + memcpy(&scan->private_ip, &hdr->private_ip, sizeof(struct peer_addr)); + memcpy(&scan->mac_addr, hdr->src_mac, 6); + scan->last_seen = time(NULL); // FIX aggiungere un timeout + scan->next = known_peers; + scan->sinfo = *sinfo; + known_peers = scan; + + traceEvent(TRACE_NORMAL, "Registered new node [public_ip=(%d)%s:%d][private_ip=%s:%d][mac=%s][community=%s]", + scan->public_ip.family, + intoa(ntohl(scan->public_ip.addr_type.v4_addr), buf, sizeof(buf)), + ntohs(scan->public_ip.port), + intoa(ntohl(scan->private_ip.addr_type.v4_addr), buf1, sizeof(buf1)), + ntohs(scan->private_ip.port), + macaddr_str(scan->mac_addr, mac_buf, sizeof(mac_buf)), + scan->community_name); +} + +/* *********************************************** */ + +static void deregister_peer(struct n2n_packet_header *hdr, + struct peer_addr *sender) { + struct peer_info *scan = known_peers, *prev = NULL; + ipstr_t buf, buf1; + + while(scan != NULL) { + if((strcmp(scan->community_name, hdr->community_name) == 0) + && (memcmp(&scan->mac_addr, hdr->src_mac, 6) == 0)) { + /* Overwrite existing peer */ + if(prev == NULL) + known_peers = scan->next; + else + prev->next = scan->next; + + traceEvent(TRACE_INFO, "Degistered node [public_ip=%s:%d][private_ip=%s:%d]", + intoa(ntohl(scan->public_ip.addr_type.v4_addr), buf, sizeof(buf)), + ntohs(scan->public_ip.port), + intoa(ntohl(scan->private_ip.addr_type.v4_addr), buf1, sizeof(buf1)), + ntohs(scan->private_ip.port)); + + free(scan); + return; + } + + scan = scan->next; + } + + traceEvent(TRACE_WARNING, "Unable to delete specified peer [%s:%d]", + intoa(ntohl(sender->addr_type.v4_addr), buf, sizeof(buf)), + ntohs(sender->port)); +} + +/* *********************************************** */ + +/* *********************************************** */ + +static const struct option long_options[] = { + { "community", required_argument, NULL, 'c' }, + { "listening-port", required_argument, NULL, 'l' }, + { "help" , no_argument, NULL, 'h' }, + { "verbose", no_argument, NULL, 'v' }, + { NULL, 0, NULL, 0 } +}; + +/* *********************************************** */ + + +/** Forward a L2 packet to every edge registered for the community of the + * originator. + * + * @return number of copies of the packet sent + */ +static size_t broadcast_packet(char *packet, u_int packet_len, + struct peer_addr *sender, + n2n_sock_info_t * sinfo, + struct n2n_packet_header *hdr ) +{ + size_t numsent=0; + struct peer_info *scan; + + scan = known_peers; + while(scan != NULL) { + if((strcmp(scan->community_name, hdr->community_name) == 0) + && (memcmp(sender, &scan->public_ip, sizeof(struct peer_addr)) /* No L3 self-send */) ) + { + int data_sent_len; + size_t len = packet_len; + + data_sent_len = send_data( &(scan->sinfo), packet, &len, &scan->public_ip, 0); + + if(data_sent_len != len) + { + ++(supernode_stats.errors); + traceEvent(TRACE_WARNING, "sendto() [sent=%d][attempted_to_send=%d] [%s]\n", + data_sent_len, len, strerror(errno)); + } + else + { + ipstr_t buf; + ipstr_t buf1; + + ++numsent; + ++(supernode_stats.pkts); + traceEvent(TRACE_INFO, "Sent multicast message to remote node [%s:%d][mac=%s]", + intoa(ntohl(scan->public_ip.addr_type.v4_addr), buf, sizeof(buf)), + ntohs(scan->public_ip.port), + macaddr_str(scan->mac_addr, buf1, sizeof(buf1))); + } + } + + scan = scan->next; + } /* while */ + + + return numsent; +} + + +/** Forward a L2 packet. This may involve a broadcast operation. + * + * Rules are as follows: + * + * 1. If the dest MAC is a multicast address, broadcast to all edges in the + * community. + * + * 2. If the dest MAC is known forward to the destination edge only. + * Else broadcast to all edges in the community. + * + * @return number of copies of the packet sent + */ +static size_t forward_packet(char *packet, u_int packet_len, + struct peer_addr *sender, + n2n_sock_info_t * sinfo, + struct n2n_packet_header *hdr ) +{ + size_t numsent=0; + u_int8_t is_dst_broad_multi_cast; + struct peer_info *scan; + + ipstr_t buf; + ipstr_t buf1; + + hdr->ttl++; /* FIX discard packets with a high TTL */ + is_dst_broad_multi_cast = is_multi_broadcast(hdr->dst_mac); + + /* Put the original packet sender (public) address */ + memcpy(&hdr->public_ip, sender, sizeof(struct peer_addr)); + hdr->sent_by_supernode = 1; + + marshall_n2n_packet_header( (u_int8_t *)packet, hdr ); + + + if ( is_dst_broad_multi_cast ) + { + traceEvent(TRACE_INFO, "Broadcasting. Multicast address [mac=%s]", + macaddr_str(hdr->dst_mac, buf, sizeof(buf))); + + numsent = broadcast_packet( packet, packet_len, sender, sinfo, hdr ); + } + else + { + scan = find_peer_by_mac( known_peers, hdr->dst_mac ); + if ( scan ) + { + int data_sent_len; + size_t len = packet_len; + + data_sent_len = send_data( &(scan->sinfo), packet, &len, &scan->public_ip, 0); + + if(data_sent_len != len) + { + ++(supernode_stats.errors); + traceEvent(TRACE_WARNING, "sendto() [sent=%d][attempted_to_send=%d] [%s]\n", + data_sent_len, len, strerror(errno)); + } + else { + ++(supernode_stats.pkts); + traceEvent(TRACE_INFO, "Sent message to remote node [%s:%d][mac=%s]", + intoa(ntohl(scan->public_ip.addr_type.v4_addr), buf, sizeof(buf)), + ntohs(scan->public_ip.port), + macaddr_str(scan->mac_addr, buf1, sizeof(buf1))); + } + + numsent = 1; + } + else + { + traceEvent(TRACE_INFO, "Broadcasting because unknown dest [mac=%s]", + macaddr_str(hdr->dst_mac, buf, sizeof(buf))); + numsent = broadcast_packet( packet, packet_len, sender, sinfo, hdr ); + } + } + + return numsent; +} + +static void handle_packet(char *packet, u_int packet_len, + struct peer_addr *sender, + n2n_sock_info_t * sinfo) { + ipstr_t buf; + + traceEvent(TRACE_INFO, "Received message from node [%s:%d]", + intoa(ntohl(sender->addr_type.v4_addr), buf, sizeof(buf)), + ntohs(sender->port)); + + if(packet_len < N2N_PKT_HDR_SIZE) + traceEvent(TRACE_WARNING, "Received packet too short [len=%d]\n", packet_len); + else { + struct n2n_packet_header hdr_storage; + struct n2n_packet_header *hdr = &hdr_storage; + + unmarshall_n2n_packet_header( hdr, (u_int8_t *)packet ); + + if(hdr->version != N2N_VERSION) { + traceEvent(TRACE_WARNING, + "Received packet with unknown protocol version (%d): discarded\n", + hdr->version); + return; + } + + if(hdr->msg_type == MSG_TYPE_REGISTER) + { + register_peer(hdr, sender, sinfo); + } + else if(hdr->msg_type == MSG_TYPE_DEREGISTER) { + deregister_peer(hdr, sender); + } else if(hdr->msg_type == MSG_TYPE_PACKET) { + forward_packet( packet, packet_len, sender, sinfo, hdr ); + } else { + traceEvent(TRACE_WARNING, "Unable to handle packet type %d: ignored\n", + hdr->msg_type); + } + } +} + +/* *********************************************** */ + +static +#ifdef WIN32 +DWORD tcpReadThread(LPVOID lpArg) +#else + void* tcpReadThread(void *lpArg) +#endif +{ + n2n_sock_info_t sinfo; + char c[1600]; + int new_line = 0; + + sinfo.sock=(int)lpArg; + sinfo.is_udp_socket=0; /* TCP in this case */ + + traceEvent(TRACE_NORMAL, "Handling sock_fd %d", sinfo.sock); + + while(1) { + int rc; + + if((rc = recv(sinfo.sock, c, 2, 0)) > 0) { + if((c[0] == '\r') && (c[1] == '\n')) { + if(!new_line) + new_line = 1; + else + break; /* Double \r\n\r\n, the http header is over */ + } else + printf("%c%c [%d][%d] ", c[0], c[1], c[0], c[1]); fflush(stdout); + } else { + traceEvent(TRACE_NORMAL, "recv() error [rc=%d][%s]", rc, strerror(errno)); + break; + } + } + + /* Beginning of n2n protocol over TCP */ + c[5] = 0; + + while(1) { + int rc; + + // FIX: add select + if((rc = recv(sinfo.sock, c, 4, 0)) == 4) { + int len = atoi(c); + socklen_t from_len = sizeof(struct sockaddr_in ); + struct sockaddr_in from; + + /* Check packet length */ + if((len <= 0) || (len >= 1600)) break; + rc = recvfrom(sinfo.sock, c, len, 0, (struct sockaddr*)&from, &from_len); + + if((rc <= 0) || (rc != len)) + break; + else { + struct peer_addr _from; + + sockaddr_in2peer_addr(&from, &_from); + handle_packet(c, len, &_from, &sinfo); + } + } else + break; + } + + closesocket(sinfo.sock); +#ifdef WIN32 + return(0); +#else + return(NULL); +#endif +} + + +/* *********************************************** */ + +static void startTcpReadThread(int sock_fd) { +#ifdef WIN32 + HANDLE hThread; + DWORD dwThreadId; + + hThread = CreateThread(NULL, /* no security attributes */ + 0, /* use default stack size */ + (LPTHREAD_START_ROUTINE)tcpReadThread, /* thread function */ + (void*)sock_fd, /* argument to thread function */ + 0, /* use default creation flags */ + &dwThreadId); /* returns the thread identifier */ +#else + int rc; + pthread_t threadId; + + rc = pthread_create(&threadId, NULL, tcpReadThread, (void*)sock_fd); +#endif +} + +/* *********************************************** */ + +int main(int argc, char* argv[]) { + int opt, local_port = 0; + n2n_sock_info_t udp_sinfo; + n2n_sock_info_t tcp_sinfo; + + optarg = NULL; + while((opt = getopt_long(argc, argv, "l:vh", long_options, NULL)) != EOF) { + switch (opt) { + case 'l': /* local-port */ + local_port = atoi(optarg); + break; + case 'h': /* help */ + help(); + break; + case 'v': /* verbose */ + traceLevel = 3; + break; + } + } + + if(!(local_port)) + help(); + + udp_sinfo.is_udp_socket=1; + udp_sinfo.sock = open_socket(local_port, 1, 0); + if(udp_sinfo.sock < 0) return(-1); + + tcp_sinfo.is_udp_socket=0; + tcp_sinfo.sock = open_socket(local_port, 0, 1); + if(tcp_sinfo.sock < 0) return(-1); + + traceEvent(TRACE_NORMAL, "Supernode ready: listening on port %d [TCP/UDP]", local_port); + + while(1) { + int rc, max_sock; + fd_set socket_mask; + struct timeval wait_time; + + FD_ZERO(&socket_mask); + max_sock = max(udp_sinfo.sock, tcp_sinfo.sock); + FD_SET(udp_sinfo.sock, &socket_mask); + FD_SET(tcp_sinfo.sock, &socket_mask); + + wait_time.tv_sec = 10; wait_time.tv_usec = 0; + rc = select(max_sock+1, &socket_mask, NULL, NULL, &wait_time); + + if(rc > 0) { + if(FD_ISSET(udp_sinfo.sock, &socket_mask)) { + char packet[2048]; + size_t len; + struct peer_addr sender; + u_int8_t discarded_pkt; + struct n2n_packet_header hdr; + + len = receive_data( &udp_sinfo, packet, sizeof(packet), &sender, &discarded_pkt, NULL, 0, &hdr); + + if(len <= 0) + traceEvent(TRACE_WARNING, "recvfrom()=%d [%s]\n", len, strerror(errno)); + else { + handle_packet(packet, len, &sender, &udp_sinfo); + } + } else if(FD_ISSET(tcp_sinfo.sock, &socket_mask)) { + struct sockaddr from; + int from_len = sizeof(from); + int new_sock = accept(tcp_sinfo.sock, (struct sockaddr*)&from, + (socklen_t*)&from_len); + + if(new_sock < 0) { + traceEvent(TRACE_WARNING, "TCP connection accept() failed [%s]\n", strerror(errno)); + } else { + startTcpReadThread(new_sock); + } + } + } + + purge_expired_registrations( &known_peers ); + } /* while */ + + closesocket(udp_sinfo.sock); + closesocket(tcp_sinfo.sock); + + return(0); +} diff --git a/tuntap_freebsd.c b/tuntap_freebsd.c new file mode 100644 index 0000000..f4a03a8 --- /dev/null +++ b/tuntap_freebsd.c @@ -0,0 +1,124 @@ +/* + * (C) 2007-08 - Luca Deri + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not see see + */ + +#include "n2n.h" + +#ifdef __FreeBSD__ + +void tun_close(tuntap_dev *device); + +/* ********************************** */ + +#define N2N_FREEBSD_TAPDEVICE_SIZE 32 +int tuntap_open(tuntap_dev *device /* ignored */, + char *dev, + char *device_ip, + char *device_mask, + const char * device_mac ) { + int i; + char tap_device[N2N_FREEBSD_TAPDEVICE_SIZE]; + + for (i = 0; i < 255; i++) { + snprintf(tap_device, sizeof(tap_device), "/dev/tap%d", i); + + device->fd = open(tap_device, O_RDWR); + if(device->fd > 0) { + traceEvent(TRACE_NORMAL, "Succesfully open %s", tap_device); + break; + } + } + + if(device->fd < 0) { + traceEvent(TRACE_ERROR, "Unable to open tap device"); + return(-1); + } else { + char buf[256]; + FILE *fd; + + device->ip_addr = inet_addr(device_ip); + + if ( device_mac ) + { + /* FIXME - This is not tested. Might be wrong syntax for OS X */ + + /* Set the hw address before bringing the if up. */ + snprintf(buf, sizeof(buf), "ifconfig tap%d ether %s", + i, device_mac); + system(buf); + } + + snprintf(buf, sizeof(buf), "ifconfig tap%d %s netmask %s mtu 1400 up", + i, device_ip, device_mask); + system(buf); + + traceEvent(TRACE_NORMAL, "Interface tap%d up and running (%s/%s)", + i, device_ip, device_mask); + + /* Read MAC address */ + + snprintf(buf, sizeof(buf), "ifconfig tap%d |grep ether|cut -c 8-24", i); + /* traceEvent(TRACE_INFO, "%s", buf); */ + + fd = popen(buf, "r"); + if(fd < 0) { + tun_close(device); + return(-1); + } else { + int a, b, c, d, e, f; + + buf[0] = 0; + fgets(buf, sizeof(buf), fd); + pclose(fd); + + if(buf[0] == '\0') { + traceEvent(TRACE_ERROR, "Unable to read tap%d interface MAC address"); + exit(0); + } + + traceEvent(TRACE_NORMAL, "Interface tap%d mac %s", i, buf); + if(sscanf(buf, "%02x:%02x:%02x:%02x:%02x:%02x", &a, &b, &c, &d, &e, &f) == 6) { + device->mac_addr[0] = a, device->mac_addr[1] = b; + device->mac_addr[2] = c, device->mac_addr[3] = d; + device->mac_addr[4] = e, device->mac_addr[5] = f; + } + } + } + + + /* read_mac(dev, device->mac_addr); */ + return(device->fd); +} + +/* ********************************** */ + +int tuntap_read(struct tuntap_dev *tuntap, unsigned char *buf, int len) { + return(read(tuntap->fd, buf, len)); +} + +/* ********************************** */ + +int tuntap_write(struct tuntap_dev *tuntap, unsigned char *buf, int len) { + return(write(tuntap->fd, buf, len)); +} + +/* ********************************** */ + +void tuntap_close(struct tuntap_dev *tuntap) { + close(tuntap->fd); +} + +#endif diff --git a/tuntap_linux.c b/tuntap_linux.c new file mode 100644 index 0000000..7e90ea6 --- /dev/null +++ b/tuntap_linux.c @@ -0,0 +1,122 @@ +/* + * (C) 2007-08 - Luca Deri + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see +*/ + +#include "n2n.h" + +#ifdef __linux__ + +static void read_mac(char *ifname, char *mac_addr) { + int _sock, res; + struct ifreq ifr; + macstr_t mac_addr_buf; + + memset (&ifr,0,sizeof(struct ifreq)); + + /* Dummy socket, just to make ioctls with */ + _sock=socket(PF_INET, SOCK_DGRAM, 0); + strcpy(ifr.ifr_name, ifname); + res = ioctl(_sock,SIOCGIFHWADDR,&ifr); + if (res<0) { + perror ("Get hw addr"); + } else + memcpy(mac_addr, ifr.ifr_ifru.ifru_hwaddr.sa_data, 6); + + traceEvent(TRACE_NORMAL, "Interface %s has MAC %s", + ifname, + macaddr_str(mac_addr, mac_addr_buf, sizeof(mac_addr_buf))); + close(_sock); +} + +/* ********************************** */ +/** @brief Open and configure the TAP device for packet read/write. + * + * This routine creates the interface via the tuntap driver then uses ifconfig + * to configure address/mask and MTU. + * + * @param device - [inout] a device info holder object + * @param dev - user-defined name for the new iface, + * if NULL system will assign a name + * @param device_ip - address of iface + * @param device_mask - netmask for device_ip + * + * @return - negative value on error + * - non-negative file-descriptor on success + */ +int tuntap_open(tuntap_dev *device, + char *dev, /* user-definable interface name, eg. edge0 */ + char *device_ip, + char *device_mask, + const char * device_mac ) { + char *tuntap_device = "/dev/net/tun"; +#define N2N_LINUX_SYSTEMCMD_SIZE 128 + char buf[N2N_LINUX_SYSTEMCMD_SIZE]; + struct ifreq ifr; + int rc; + + device->fd = open(tuntap_device, O_RDWR); + if(device->fd < 0) { + printf("ERROR: ioctl() [%s][%d]\n", strerror(errno), rc); + return -1; + } + + memset(&ifr, 0, sizeof(ifr)); + ifr.ifr_flags = IFF_TAP|IFF_NO_PI; /* Want a TAP device for layer 2 frames. */ + strncpy(ifr.ifr_name, dev, IFNAMSIZ); + rc = ioctl(device->fd, TUNSETIFF, (void *)&ifr); + + if(rc < 0) { + traceEvent(TRACE_ERROR, "ioctl() [%s][%d]\n", strerror(errno), rc); + close(device->fd); + return -1; + } + + /* REVISIT: BbMja7: MTU should be related to MTU of the interface the tuntap + * is built on. The value 1400 assumes an eth iface with MTU 1500, but would + * fail for ppp at mtu=576. + */ + if ( device_mac ) + { + /* Set the hw address before bringing the if up. */ + snprintf(buf, sizeof(buf), "/sbin/ifconfig %s hw ether %s", + ifr.ifr_name, device_mac ); + system(buf); + traceEvent(TRACE_INFO, "Setting MAC: %s", buf); + } + + snprintf(buf, sizeof(buf), "/sbin/ifconfig %s %s netmask %s mtu 1400 up", + ifr.ifr_name, device_ip, device_mask); + system(buf); + traceEvent(TRACE_INFO, "Bringing up: %s", buf); + + device->ip_addr = inet_addr(device_ip); + read_mac(dev, (char*)device->mac_addr); + return(device->fd); +} + +int tuntap_read(struct tuntap_dev *tuntap, unsigned char *buf, int len) { + return(read(tuntap->fd, buf, len)); +} + +int tuntap_write(struct tuntap_dev *tuntap, unsigned char *buf, int len) { + return(write(tuntap->fd, buf, len)); +} + +void tuntap_close(struct tuntap_dev *tuntap) { + close(tuntap->fd); +} + +#endif /* #ifdef __linux__ */ diff --git a/tuntap_osx.c b/tuntap_osx.c new file mode 100644 index 0000000..be8b312 --- /dev/null +++ b/tuntap_osx.c @@ -0,0 +1,124 @@ +/* + * (C) 2007-08 - Luca Deri + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not see see + */ + +#include "n2n.h" + +#ifdef _DARWIN_ + +void tun_close(tuntap_dev *device); + +/* ********************************** */ + +#define N2N_OSX_TAPDEVICE_SIZE 32 +int tuntap_open(tuntap_dev *device /* ignored */, + char *dev, + char *device_ip, + char *device_mask, + const char * device_mac ) { + int i; + char tap_device[N2N_OSX_TAPDEVICE_SIZE]; + + for (i = 0; i < 255; i++) { + snprintf(tap_device, sizeof(tap_device), "/dev/tap%d", i); + + device->fd = open(tap_device, O_RDWR); + if(device->fd > 0) { + traceEvent(TRACE_NORMAL, "Succesfully open %s", tap_device); + break; + } + } + + if(device->fd < 0) { + traceEvent(TRACE_ERROR, "Unable to open tap device"); + return(-1); + } else { + char buf[256]; + FILE *fd; + + device->ip_addr = inet_addr(device_ip); + + if ( device_mac ) + { + /* FIXME - This is not tested. Might be wrong syntax for OS X */ + + /* Set the hw address before bringing the if up. */ + snprintf(buf, sizeof(buf), "ifconfig tap%d ether %s", + i, device_mac); + system(buf); + } + + snprintf(buf, sizeof(buf), "ifconfig tap%d %s netmask %s mtu 1400 up", + i, device_ip, device_mask); + system(buf); + + traceEvent(TRACE_NORMAL, "Interface tap%d up and running (%s/%s)", + i, device_ip, device_mask); + + /* Read MAC address */ + + snprintf(buf, sizeof(buf), "ifconfig tap%d |grep ether|cut -c 8-24", i); + /* traceEvent(TRACE_INFO, "%s", buf); */ + + fd = popen(buf, "r"); + if(fd < 0) { + tun_close(device); + return(-1); + } else { + int a, b, c, d, e, f; + + buf[0] = 0; + fgets(buf, sizeof(buf), fd); + pclose(fd); + + if(buf[0] == '\0') { + traceEvent(TRACE_ERROR, "Unable to read tap%d interface MAC address"); + exit(0); + } + + traceEvent(TRACE_NORMAL, "Interface tap%d mac %s", i, buf); + if(sscanf(buf, "%02x:%02x:%02x:%02x:%02x:%02x", &a, &b, &c, &d, &e, &f) == 6) { + device->mac_addr[0] = a, device->mac_addr[1] = b; + device->mac_addr[2] = c, device->mac_addr[3] = d; + device->mac_addr[4] = e, device->mac_addr[5] = f; + } + } + } + + + /* read_mac(dev, device->mac_addr); */ + return(device->fd); +} + +/* ********************************** */ + +int tuntap_read(struct tuntap_dev *tuntap, unsigned char *buf, int len) { + return(read(tuntap->fd, buf, len)); +} + +/* ********************************** */ + +int tuntap_write(struct tuntap_dev *tuntap, unsigned char *buf, int len) { + return(write(tuntap->fd, buf, len)); +} + +/* ********************************** */ + +void tuntap_close(struct tuntap_dev *tuntap) { + close(tuntap->fd); +} + +#endif diff --git a/twofish.c b/twofish.c new file mode 100644 index 0000000..73a1a8e --- /dev/null +++ b/twofish.c @@ -0,0 +1,1031 @@ +/* $Id: twofish.c,v 2.0 2002/08/11 22:32:25 fknobbe Exp $ + * + * + * Copyright (C) 1997-2000 The Cryptix Foundation Limited. + * Copyright (C) 2000 Farm9. + * Copyright (C) 2001 Frank Knobbe. + * All rights reserved. + * + * For Cryptix code: + * Use, modification, copying and distribution of this software is subject + * the terms and conditions of the Cryptix General Licence. You should have + * received a copy of the Cryptix General Licence along with this library; + * if not, you can download a copy from http://www.cryptix.org/ . + * + * For Farm9: + * --- jojo@farm9.com, August 2000, converted from Java to C++, added CBC mode and + * ciphertext stealing technique, added AsciiTwofish class for easy encryption + * decryption of text strings + * + * Frank Knobbe : + * --- April 2001, converted from C++ to C, prefixed global variables + * with TwoFish, substituted some defines, changed functions to make use of + * variables supplied in a struct, modified and added routines for modular calls. + * Cleaned up the code so that defines are used instead of fixed 16's and 32's. + * Created two general purpose crypt routines for one block and multiple block + * encryption using Joh's CBC code. + * Added crypt routines that use a header (with a magic and data length). + * (Basically a major rewrite). + * + * Note: Routines labeled _TwoFish are private and should not be used + * (or with extreme caution). + * + */ + +#ifndef __TWOFISH_LIBRARY_SOURCE__ +#define __TWOFISH_LIBRARY_SOURCE__ + +#include +#include +#include +#include +#include +#include "twofish.h" + + +bool TwoFish_srand=TRUE; /* if TRUE, first call of TwoFishInit will seed rand(); */ +/* of TwoFishInit */ + +/* Fixed 8x8 permutation S-boxes */ +static const u_int8_t TwoFish_P[2][256] = + { + { /* p0 */ + 0xA9, 0x67, 0xB3, 0xE8, 0x04, 0xFD, 0xA3, 0x76, 0x9A, 0x92, 0x80, 0x78, + 0xE4, 0xDD, 0xD1, 0x38, 0x0D, 0xC6, 0x35, 0x98, 0x18, 0xF7, 0xEC, 0x6C, + 0x43, 0x75, 0x37, 0x26, 0xFA, 0x13, 0x94, 0x48, 0xF2, 0xD0, 0x8B, 0x30, + 0x84, 0x54, 0xDF, 0x23, 0x19, 0x5B, 0x3D, 0x59, 0xF3, 0xAE, 0xA2, 0x82, + 0x63, 0x01, 0x83, 0x2E, 0xD9, 0x51, 0x9B, 0x7C, 0xA6, 0xEB, 0xA5, 0xBE, + 0x16, 0x0C, 0xE3, 0x61, 0xC0, 0x8C, 0x3A, 0xF5, 0x73, 0x2C, 0x25, 0x0B, + 0xBB, 0x4E, 0x89, 0x6B, 0x53, 0x6A, 0xB4, 0xF1, 0xE1, 0xE6, 0xBD, 0x45, + 0xE2, 0xF4, 0xB6, 0x66, 0xCC, 0x95, 0x03, 0x56, 0xD4, 0x1C, 0x1E, 0xD7, + 0xFB, 0xC3, 0x8E, 0xB5, 0xE9, 0xCF, 0xBF, 0xBA, 0xEA, 0x77, 0x39, 0xAF, + 0x33, 0xC9, 0x62, 0x71, 0x81, 0x79, 0x09, 0xAD, 0x24, 0xCD, 0xF9, 0xD8, + 0xE5, 0xC5, 0xB9, 0x4D, 0x44, 0x08, 0x86, 0xE7, 0xA1, 0x1D, 0xAA, 0xED, + 0x06, 0x70, 0xB2, 0xD2, 0x41, 0x7B, 0xA0, 0x11, 0x31, 0xC2, 0x27, 0x90, + 0x20, 0xF6, 0x60, 0xFF, 0x96, 0x5C, 0xB1, 0xAB, 0x9E, 0x9C, 0x52, 0x1B, + 0x5F, 0x93, 0x0A, 0xEF, 0x91, 0x85, 0x49, 0xEE, 0x2D, 0x4F, 0x8F, 0x3B, + 0x47, 0x87, 0x6D, 0x46, 0xD6, 0x3E, 0x69, 0x64, 0x2A, 0xCE, 0xCB, 0x2F, + 0xFC, 0x97, 0x05, 0x7A, 0xAC, 0x7F, 0xD5, 0x1A, 0x4B, 0x0E, 0xA7, 0x5A, + 0x28, 0x14, 0x3F, 0x29, 0x88, 0x3C, 0x4C, 0x02, 0xB8, 0xDA, 0xB0, 0x17, + 0x55, 0x1F, 0x8A, 0x7D, 0x57, 0xC7, 0x8D, 0x74, 0xB7, 0xC4, 0x9F, 0x72, + 0x7E, 0x15, 0x22, 0x12, 0x58, 0x07, 0x99, 0x34, 0x6E, 0x50, 0xDE, 0x68, + 0x65, 0xBC, 0xDB, 0xF8, 0xC8, 0xA8, 0x2B, 0x40, 0xDC, 0xFE, 0x32, 0xA4, + 0xCA, 0x10, 0x21, 0xF0, 0xD3, 0x5D, 0x0F, 0x00, 0x6F, 0x9D, 0x36, 0x42, + 0x4A, 0x5E, 0xC1, 0xE0 + }, + { /* p1 */ + 0x75, 0xF3, 0xC6, 0xF4, 0xDB, 0x7B, 0xFB, 0xC8, 0x4A, 0xD3, 0xE6, 0x6B, + 0x45, 0x7D, 0xE8, 0x4B, 0xD6, 0x32, 0xD8, 0xFD, 0x37, 0x71, 0xF1, 0xE1, + 0x30, 0x0F, 0xF8, 0x1B, 0x87, 0xFA, 0x06, 0x3F, 0x5E, 0xBA, 0xAE, 0x5B, + 0x8A, 0x00, 0xBC, 0x9D, 0x6D, 0xC1, 0xB1, 0x0E, 0x80, 0x5D, 0xD2, 0xD5, + 0xA0, 0x84, 0x07, 0x14, 0xB5, 0x90, 0x2C, 0xA3, 0xB2, 0x73, 0x4C, 0x54, + 0x92, 0x74, 0x36, 0x51, 0x38, 0xB0, 0xBD, 0x5A, 0xFC, 0x60, 0x62, 0x96, + 0x6C, 0x42, 0xF7, 0x10, 0x7C, 0x28, 0x27, 0x8C, 0x13, 0x95, 0x9C, 0xC7, + 0x24, 0x46, 0x3B, 0x70, 0xCA, 0xE3, 0x85, 0xCB, 0x11, 0xD0, 0x93, 0xB8, + 0xA6, 0x83, 0x20, 0xFF, 0x9F, 0x77, 0xC3, 0xCC, 0x03, 0x6F, 0x08, 0xBF, + 0x40, 0xE7, 0x2B, 0xE2, 0x79, 0x0C, 0xAA, 0x82, 0x41, 0x3A, 0xEA, 0xB9, + 0xE4, 0x9A, 0xA4, 0x97, 0x7E, 0xDA, 0x7A, 0x17, 0x66, 0x94, 0xA1, 0x1D, + 0x3D, 0xF0, 0xDE, 0xB3, 0x0B, 0x72, 0xA7, 0x1C, 0xEF, 0xD1, 0x53, 0x3E, + 0x8F, 0x33, 0x26, 0x5F, 0xEC, 0x76, 0x2A, 0x49, 0x81, 0x88, 0xEE, 0x21, + 0xC4, 0x1A, 0xEB, 0xD9, 0xC5, 0x39, 0x99, 0xCD, 0xAD, 0x31, 0x8B, 0x01, + 0x18, 0x23, 0xDD, 0x1F, 0x4E, 0x2D, 0xF9, 0x48, 0x4F, 0xF2, 0x65, 0x8E, + 0x78, 0x5C, 0x58, 0x19, 0x8D, 0xE5, 0x98, 0x57, 0x67, 0x7F, 0x05, 0x64, + 0xAF, 0x63, 0xB6, 0xFE, 0xF5, 0xB7, 0x3C, 0xA5, 0xCE, 0xE9, 0x68, 0x44, + 0xE0, 0x4D, 0x43, 0x69, 0x29, 0x2E, 0xAC, 0x15, 0x59, 0xA8, 0x0A, 0x9E, + 0x6E, 0x47, 0xDF, 0x34, 0x35, 0x6A, 0xCF, 0xDC, 0x22, 0xC9, 0xC0, 0x9B, + 0x89, 0xD4, 0xED, 0xAB, 0x12, 0xA2, 0x0D, 0x52, 0xBB, 0x02, 0x2F, 0xA9, + 0xD7, 0x61, 0x1E, 0xB4, 0x50, 0x04, 0xF6, 0xC2, 0x16, 0x25, 0x86, 0x56, + 0x55, 0x09, 0xBE, 0x91 + } + }; + +static bool TwoFish_MDSready=FALSE; +static u_int32_t TwoFish_MDS[4][256]; /* TwoFish_MDS matrix */ + + +#define TwoFish_LFSR1(x) (((x)>>1)^(((x)&0x01)?TwoFish_MDS_GF_FDBK/2:0)) +#define TwoFish_LFSR2(x) (((x)>>2)^(((x)&0x02)?TwoFish_MDS_GF_FDBK/2:0)^(((x)&0x01)?TwoFish_MDS_GF_FDBK/4:0)) + +#define TwoFish_Mx_1(x) ((u_int32_t)(x)) /* force result to dword so << will work */ +#define TwoFish_Mx_X(x) ((u_int32_t)((x)^TwoFish_LFSR2(x))) /* 5B */ +#define TwoFish_Mx_Y(x) ((u_int32_t)((x)^TwoFish_LFSR1(x)^TwoFish_LFSR2(x))) /* EF */ +#define TwoFish_RS_rem(x) { u_int8_t b=(u_int8_t)(x>>24); u_int32_t g2=((b<<1)^((b&0x80)?TwoFish_RS_GF_FDBK:0))&0xFF; u_int32_t g3=((b>>1)&0x7F)^((b&1)?TwoFish_RS_GF_FDBK>>1:0)^g2; x=(x<<8)^(g3<<24)^(g2<<16)^(g3<<8)^b; } + +/*#define TwoFish__b(x,N) (((u_int8_t *)&x)[((N)&3)^TwoFish_ADDR_XOR])*/ /* pick bytes out of a dword */ + +#define TwoFish_b0(x) TwoFish__b(x,0) /* extract LSB of u_int32_t */ +#define TwoFish_b1(x) TwoFish__b(x,1) +#define TwoFish_b2(x) TwoFish__b(x,2) +#define TwoFish_b3(x) TwoFish__b(x,3) /* extract MSB of u_int32_t */ + +u_int8_t TwoFish__b(u_int32_t x,int n) +{ n&=3; + while(n-->0) + x>>=8; + return (u_int8_t)x; +} + + +/* TwoFish Initialization + * + * This routine generates a global data structure for use with TwoFish, + * initializes important values (such as subkeys, sBoxes), generates subkeys + * and precomputes the MDS matrix if not already done. + * + * Input: User supplied password (will be appended by default password of 'SnortHas2FishEncryptionRoutines!') + * + * Output: Pointer to TWOFISH structure. This data structure contains key dependent data. + * This pointer is used with all other crypt functions. + */ + +TWOFISH *TwoFishInit(const u_int8_t *userkey, u_int32_t keysize) +{ TWOFISH *tfdata; + int i,x,m; + u_int8_t tkey[TwoFish_KEY_LENGTH+40]; + + memset( tkey, 0, TwoFish_KEY_LENGTH+40 ); + tfdata=(TWOFISH *)malloc(sizeof(TWOFISH)); /* allocate the TwoFish structure */ + if(tfdata!=NULL) + { + + /* Changes here prevented a dangerous random key segment for keys of length < TwoFish_KEY_LENGTH */ + if(keysize > 0) + { + memcpy( tkey, userkey, keysize ); /* The rest will be zeros */ + } + else + { + memcpy( tkey, TwoFish_DEFAULT_PW, TwoFish_DEFAULT_PW_LEN ); /* if no key defined, use default password */ + } + + /* This loop is awful - surely a loop on memcpy() would be clearer and more efficient */ + for(i=0,x=0,m=keysize;ikey[i]=tkey[x++]; /* fill the whole keyspace with repeating key. */ + if(x==m) + x=0; + } + + if(!TwoFish_MDSready) + _TwoFish_PrecomputeMDSmatrix(); /* "Wake Up, Neo" */ + _TwoFish_MakeSubKeys(tfdata); /* generate subkeys */ + _TwoFish_ResetCBC(tfdata); /* reset the CBC */ + tfdata->output=NULL; /* nothing to output yet */ + tfdata->dontflush=FALSE; /* reset decrypt skip block flag */ + if(TwoFish_srand) + { + TwoFish_srand=FALSE; + /* REVISIT: BbMaj7 : Should choose something with less predictability + * particularly for embedded targets with no real-time clock. */ + srand((unsigned int)time(NULL)); + } + } + return tfdata; /* return the data pointer */ +} + + +void TwoFishDestroy(TWOFISH *tfdata) +{ if(tfdata!=NULL) + free(tfdata); +} + + +/* en/decryption with CBC mode */ +u_int32_t _TwoFish_CryptRawCBC(u_int8_t *in,u_int8_t *out,u_int32_t len,bool decrypt,TWOFISH *tfdata) +{ u_int32_t rl; + + rl=len; /* remember how much data to crypt. */ + while(len>TwoFish_BLOCK_SIZE) /* and now we process block by block. */ + { _TwoFish_BlockCrypt(in,out,TwoFish_BLOCK_SIZE,decrypt,tfdata); /* de/encrypt it. */ + in+=TwoFish_BLOCK_SIZE; /* adjust pointers. */ + out+=TwoFish_BLOCK_SIZE; + len-=TwoFish_BLOCK_SIZE; + } + if(len>0) /* if we have less than a block left... */ + _TwoFish_BlockCrypt(in,out,len,decrypt,tfdata); /* ...then we de/encrypt that too. */ + if(tfdata->qBlockDefined && !tfdata->dontflush) /* in case len was exactly one block... */ + _TwoFish_FlushOutput(tfdata->qBlockCrypt,TwoFish_BLOCK_SIZE,tfdata); /* ...we need to write the... */ + /* ...remaining bytes of the buffer */ + return rl; +} + +/* en/decryption on one block only */ +u_int32_t _TwoFish_CryptRaw16(u_int8_t *in,u_int8_t *out,u_int32_t len,bool decrypt,TWOFISH *tfdata) +{ /* qBlockPlain already zero'ed through ResetCBC */ + memcpy(tfdata->qBlockPlain,in,len); /* toss the data into it. */ + _TwoFish_BlockCrypt16(tfdata->qBlockPlain,tfdata->qBlockCrypt,decrypt,tfdata); /* encrypt just that block without CBC. */ + memcpy(out,tfdata->qBlockCrypt,TwoFish_BLOCK_SIZE); /* and return what we got */ + return TwoFish_BLOCK_SIZE; +} + +/* en/decryption without reset of CBC and output assignment */ +u_int32_t _TwoFish_CryptRaw(u_int8_t *in,u_int8_t *out,u_int32_t len,bool decrypt,TWOFISH *tfdata) +{ + if(in!=NULL && out!=NULL && len>0 && tfdata!=NULL) /* if we have valid data, then... */ + { if(len>TwoFish_BLOCK_SIZE) /* ...check if we have more than one block. */ + return _TwoFish_CryptRawCBC(in,out,len,decrypt,tfdata); /* if so, use the CBC routines... */ + else + return _TwoFish_CryptRaw16(in,out,len,decrypt,tfdata); /* ...otherwise just do one block. */ + } + return 0; +} + + +/* TwoFish Raw Encryption + * + * Does not use header, but does use CBC (if more than one block has to be encrypted). + * + * Input: Pointer to the buffer of the plaintext to be encrypted. + * Pointer to the buffer receiving the ciphertext. + * The length of the plaintext buffer. + * The TwoFish structure. + * + * Output: The amount of bytes encrypted if successful, otherwise 0. + */ + +u_int32_t TwoFishEncryptRaw(u_int8_t *in, + u_int8_t *out, + u_int32_t len, + TWOFISH *tfdata) +{ _TwoFish_ResetCBC(tfdata); /* reset CBC flag. */ + tfdata->output=out; /* output straight into output buffer. */ + return _TwoFish_CryptRaw(in,out,len,FALSE,tfdata); /* and go for it. */ +} + +/* TwoFish Raw Decryption + * + * Does not use header, but does use CBC (if more than one block has to be decrypted). + * + * Input: Pointer to the buffer of the ciphertext to be decrypted. + * Pointer to the buffer receiving the plaintext. + * The length of the ciphertext buffer (at least one cipher block). + * The TwoFish structure. + * + * Output: The amount of bytes decrypted if successful, otherwise 0. + */ + +u_int32_t TwoFishDecryptRaw(u_int8_t *in, + u_int8_t *out, + u_int32_t len, + TWOFISH *tfdata) +{ _TwoFish_ResetCBC(tfdata); /* reset CBC flag. */ + tfdata->output=out; /* output straight into output buffer. */ + return _TwoFish_CryptRaw(in,out,len,TRUE,tfdata); /* and go for it. */ +} + +/* TwoFish Free + * + * Free's the allocated buffer. + * + * Input: Pointer to the TwoFish structure + * + * Output: (none) + */ + +void TwoFishFree(TWOFISH *tfdata) +{ if(tfdata->output!=NULL) /* if a valid buffer is present... */ + { free(tfdata->output); /* ...then we free it for you... */ + tfdata->output=NULL; /* ...and mark as such. */ + } +} + +/* TwoFish Set Output + * + * If you want to allocate the output buffer yourself, + * then you can set it with this function. + * + * Input: Pointer to your output buffer + * Pointer to the TwoFish structure + * + * Output: (none) + */ + +void TwoFishSetOutput(u_int8_t *outp,TWOFISH *tfdata) +{ tfdata->output=outp; /* (do we really need a function for this?) */ +} + +/* TwoFish Alloc + * + * Allocates enough memory for the output buffer that would be required + * + * Input: Length of the plaintext. + * Boolean flag for BinHex Output. + * Pointer to the TwoFish structure. + * + * Output: Returns a pointer to the memory allocated. + */ + +void *TwoFishAlloc(u_int32_t len,bool binhex,bool decrypt,TWOFISH *tfdata) +{ + /* TwoFishFree(tfdata); */ /* (don't for now) discard whatever was allocated earlier. */ + if(decrypt) /* if decrypting... */ + { if(binhex) /* ...and input is binhex encoded... */ + len/=2; /* ...use half as much for output. */ + len-=TwoFish_BLOCK_SIZE; /* Also, subtract the size of the header. */ + } + else + { len+=TwoFish_BLOCK_SIZE; /* the size is just increased by the header... */ + if(binhex) + len*=2; /* ...and doubled if output is to be binhexed. */ + } + tfdata->output=malloc(len+TwoFish_BLOCK_SIZE);/* grab some memory...plus some extra (it's running over somewhere, crashes without extra padding) */ + + return tfdata->output; /* ...and return to caller. */ +} + +/* bin2hex and hex2bin conversion */ +void _TwoFish_BinHex(u_int8_t *buf,u_int32_t len,bool bintohex) +{ u_int8_t *pi,*po,c; + + if(bintohex) + { for(pi=buf+len-1,po=buf+(2*len)-1;len>0;pi--,po--,len--) /* let's start from the end of the bin block. */ + { c=*pi; /* grab value. */ + c&=15; /* use lower 4 bits. */ + if(c>9) /* convert to ascii. */ + c+=('a'-10); + else + c+='0'; + *po--=c; /* set the lower nibble. */ + c=*pi; /* grab value again. */ + c>>=4; /* right shift 4 bits. */ + c&=15; /* make sure we only have 4 bits. */ + if(c>9) /* convert to ascii. */ + c+=('a'-10); + else + c+='0'; + *po=c; /* set the higher nibble. */ + } /* and keep going. */ + } + else + { for(pi=buf,po=buf;len>0;pi++,po++,len-=2) /* let's start from the beginning of the hex block. */ + { c=tolower(*pi++)-'0'; /* grab higher nibble. */ + if(c>9) /* convert to value. */ + c-=('0'-9); + *po=c<<4; /* left shit 4 bits. */ + c=tolower(*pi)-'0'; /* grab lower nibble. */ + if(c>9) /* convert to value. */ + c-=('0'-9); + *po|=c; /* and add to value. */ + } + } +} + + +/* TwoFish Encryption + * + * Uses header and CBC. If the output area has not been intialized with TwoFishAlloc, + * this routine will alloc the memory. In addition, it will include a small 'header' + * containing the magic and some salt. That way the decrypt routine can check if the + * packet got decrypted successfully, and return 0 instead of garbage. + * + * Input: Pointer to the buffer of the plaintext to be encrypted. + * Pointer to the pointer to the buffer receiving the ciphertext. + * The pointer either points to user allocated output buffer space, or to NULL, in which case + * this routine will set the pointer to the buffer allocated through the struct. + * The length of the plaintext buffer. + * Can be -1 if the input is a null terminated string, in which case we'll count for you. + * Boolean flag for BinHex Output (if used, output will be twice as large as input). + * Note: BinHex conversion overwrites (converts) input buffer! + * The TwoFish structure. + * + * Output: The amount of bytes encrypted if successful, otherwise 0. + */ + +u_int32_t TwoFishEncrypt(u_int8_t *in, + u_int8_t **out, + signed long len, + bool binhex, + TWOFISH *tfdata) +{ u_int32_t ilen,olen; + + +#if 0 +/* This is so broken it doesn't deserve to live. */ + if(len== -1) /* if we got -1 for len, we'll assume IN is a... */ + ilen=strlen(in); /* ...\0 terminated string and figure len out ourselves... */ + else + ilen=len; /* ...otherwise we trust you supply a correct length. */ +#endif + + ilen = len; + + if(in!=NULL && out!=NULL && ilen>0 && tfdata!=NULL) /* if we got usable stuff, we'll do it. */ + { if(*out==NULL) /* if OUT points to a NULL pointer... */ + *out=TwoFishAlloc(ilen,binhex,FALSE,tfdata); /* ...we'll (re-)allocate buffer space. */ + if(*out!=NULL) + { tfdata->output=*out; /* set output buffer. */ + tfdata->header.salt=rand()*65536+rand(); /* toss in some salt. */ + tfdata->header.length[0]= (u_int8_t)(ilen); + tfdata->header.length[1]= (u_int8_t)(ilen>>8); + tfdata->header.length[2]= (u_int8_t)(ilen>>16); + tfdata->header.length[3]= (u_int8_t)(ilen>>24); + memcpy(tfdata->header.magic,TwoFish_MAGIC,TwoFish_MAGIC_LEN); /* set the magic. */ + olen=TwoFish_BLOCK_SIZE; /* set output counter. */ + _TwoFish_ResetCBC(tfdata); /* reset the CBC flag */ + _TwoFish_BlockCrypt((u_int8_t *)&(tfdata->header),*out,olen,FALSE,tfdata); /* encrypt first block (without flush on 16 byte boundary). */ + olen+=_TwoFish_CryptRawCBC(in,*out+TwoFish_BLOCK_SIZE,ilen,FALSE,tfdata); /* and encrypt the rest (we do not reset the CBC flag). */ + if(binhex) /* if binhex... */ + { _TwoFish_BinHex(*out,olen,TRUE); /* ...convert output to binhex... */ + olen*=2; /* ...and size twice as large. */ + } + tfdata->output=*out; + return olen; + } + } + return 0; +} + +/* TwoFish Decryption + * + * Uses header and CBC. If the output area has not been intialized with TwoFishAlloc, + * this routine will alloc the memory. In addition, it will check the small 'header' + * containing the magic. If magic does not match we return 0. Otherwise we return the + * amount of bytes decrypted (should be the same as the length in the header). + * + * Input: Pointer to the buffer of the ciphertext to be decrypted. + * Pointer to the pointer to the buffer receiving the plaintext. + * The pointer either points to user allocated output buffer space, or to NULL, in which case + * this routine will set the pointer to the buffer allocated through the struct. + * The length of the ciphertext buffer. + * Can be -1 if the input is a null terminated binhex string, in which case we'll count for you. + * Boolean flag for BinHex Input (if used, plaintext will be half as large as input). + * Note: BinHex conversion overwrites (converts) input buffer! + * The TwoFish structure. + * + * Output: The amount of bytes decrypted if successful, otherwise 0. + */ + +u_int32_t TwoFishDecrypt(u_int8_t *in, + u_int8_t **out, + signed long len, + bool binhex, + TWOFISH *tfdata) +{ u_int32_t ilen,elen,olen; + const u_int8_t cmagic[TwoFish_MAGIC_LEN]=TwoFish_MAGIC; + u_int8_t *tbuf; + + + +#if 0 +/* This is so broken it doesn't deserve to live. */ + if(len== -1) /* if we got -1 for len, we'll assume IN is a... */ + ilen=strlen(in); /* ...\0 terminated string and figure len out ourselves... */ + else + ilen=len; /* ...otherwise we trust you supply a correct length. */ +#endif + + ilen = len; + + if(in!=NULL && out!=NULL && ilen>0 && tfdata!=NULL) /* if we got usable stuff, we'll do it. */ + { if(*out==NULL) /* if OUT points to a NULL pointer... */ + *out=TwoFishAlloc(ilen,binhex,TRUE,tfdata); /* ...we'll (re-)allocate buffer space. */ + if(*out!=NULL) + { if(binhex) /* if binhex... */ + { _TwoFish_BinHex(in,ilen,FALSE); /* ...convert input to values... */ + ilen/=2; /* ...and size half as much. */ + } + _TwoFish_ResetCBC(tfdata); /* reset the CBC flag. */ + + tbuf=(u_int8_t *)malloc(ilen+TwoFish_BLOCK_SIZE); /* get memory for data and header. */ + if(tbuf==NULL) + return 0; + tfdata->output=tbuf; /* set output to temp buffer. */ + + olen=_TwoFish_CryptRawCBC(in,tbuf,ilen,TRUE,tfdata)-TwoFish_BLOCK_SIZE; /* decrypt the whole thing. */ + memcpy(&(tfdata->header),tbuf,TwoFish_BLOCK_SIZE); /* copy first block into header. */ + tfdata->output=*out; + for(elen=0;elenheader.magic[elen]!=cmagic[elen]) + break; + if(elen==TwoFish_MAGIC_LEN) /* if magic matches then... */ + { elen=(tfdata->header.length[0]) | + (tfdata->header.length[1])<<8 | + (tfdata->header.length[2])<<16 | + (tfdata->header.length[3])<<24; /* .. we know how much to expect. */ + if(elen>olen) /* adjust if necessary. */ + elen=olen; + memcpy(*out,tbuf+TwoFish_BLOCK_SIZE,elen); /* copy data into intended output. */ + free(tbuf); + return elen; + } + free(tbuf); + } + } + return 0; +} + +void _TwoFish_PrecomputeMDSmatrix(void) /* precompute the TwoFish_MDS matrix */ +{ u_int32_t m1[2]; + u_int32_t mX[2]; + u_int32_t mY[2]; + u_int32_t i, j; + + for (i = 0; i < 256; i++) + { j = TwoFish_P[0][i] & 0xFF; /* compute all the matrix elements */ + m1[0] = j; + mX[0] = TwoFish_Mx_X( j ) & 0xFF; + mY[0] = TwoFish_Mx_Y( j ) & 0xFF; + + j = TwoFish_P[1][i] & 0xFF; + m1[1] = j; + mX[1] = TwoFish_Mx_X( j ) & 0xFF; + mY[1] = TwoFish_Mx_Y( j ) & 0xFF; + + TwoFish_MDS[0][i] = m1[TwoFish_P_00] | /* fill matrix w/ above elements */ + mX[TwoFish_P_00] << 8 | + mY[TwoFish_P_00] << 16 | + mY[TwoFish_P_00] << 24; + TwoFish_MDS[1][i] = mY[TwoFish_P_10] | + mY[TwoFish_P_10] << 8 | + mX[TwoFish_P_10] << 16 | + m1[TwoFish_P_10] << 24; + TwoFish_MDS[2][i] = mX[TwoFish_P_20] | + mY[TwoFish_P_20] << 8 | + m1[TwoFish_P_20] << 16 | + mY[TwoFish_P_20] << 24; + TwoFish_MDS[3][i] = mX[TwoFish_P_30] | + m1[TwoFish_P_30] << 8 | + mY[TwoFish_P_30] << 16 | + mX[TwoFish_P_30] << 24; + } + TwoFish_MDSready=TRUE; +} + + +void _TwoFish_MakeSubKeys(TWOFISH *tfdata) /* Expand a user-supplied key material into a session key. */ +{ u_int32_t k64Cnt = TwoFish_KEY_LENGTH / 8; + u_int32_t k32e[4]; /* even 32-bit entities */ + u_int32_t k32o[4]; /* odd 32-bit entities */ + u_int32_t sBoxKey[4]; + u_int32_t offset,i,j; + u_int32_t A, B, q=0; + u_int32_t k0,k1,k2,k3; + u_int32_t b0,b1,b2,b3; + + /* split user key material into even and odd 32-bit entities and */ + /* compute S-box keys using (12, 8) Reed-Solomon code over GF(256) */ + + + for (offset=0,i=0,j=k64Cnt-1;i<4 && offsetkey[offset++]; + k32e[i]|= tfdata->key[offset++]<<8; + k32e[i]|= tfdata->key[offset++]<<16; + k32e[i]|= tfdata->key[offset++]<<24; + k32o[i] = tfdata->key[offset++]; + k32o[i]|= tfdata->key[offset++]<<8; + k32o[i]|= tfdata->key[offset++]<<16; + k32o[i]|= tfdata->key[offset++]<<24; + sBoxKey[j] = _TwoFish_RS_MDS_Encode( k32e[i], k32o[i] ); /* reverse order */ + } + + /* compute the round decryption subkeys for PHT. these same subkeys */ + /* will be used in encryption but will be applied in reverse order. */ + i=0; + while(i < TwoFish_TOTAL_SUBKEYS) + { A = _TwoFish_F32( k64Cnt, q, k32e ); /* A uses even key entities */ + q += TwoFish_SK_BUMP; + + B = _TwoFish_F32( k64Cnt, q, k32o ); /* B uses odd key entities */ + q += TwoFish_SK_BUMP; + + B = B << 8 | B >> 24; + + A += B; + tfdata->subKeys[i++] = A; /* combine with a PHT */ + + A += B; + tfdata->subKeys[i++] = A << TwoFish_SK_ROTL | A >> (32-TwoFish_SK_ROTL); + } + + /* fully expand the table for speed */ + k0 = sBoxKey[0]; + k1 = sBoxKey[1]; + k2 = sBoxKey[2]; + k3 = sBoxKey[3]; + + for (i = 0; i < 256; i++) + { b0 = b1 = b2 = b3 = i; + switch (k64Cnt & 3) + { case 1: /* 64-bit keys */ + tfdata->sBox[ 2*i ] = TwoFish_MDS[0][(TwoFish_P[TwoFish_P_01][b0]) ^ TwoFish_b0(k0)]; + tfdata->sBox[ 2*i+1] = TwoFish_MDS[1][(TwoFish_P[TwoFish_P_11][b1]) ^ TwoFish_b1(k0)]; + tfdata->sBox[0x200+2*i ] = TwoFish_MDS[2][(TwoFish_P[TwoFish_P_21][b2]) ^ TwoFish_b2(k0)]; + tfdata->sBox[0x200+2*i+1] = TwoFish_MDS[3][(TwoFish_P[TwoFish_P_31][b3]) ^ TwoFish_b3(k0)]; + break; + case 0: /* 256-bit keys (same as 4) */ + b0 = (TwoFish_P[TwoFish_P_04][b0]) ^ TwoFish_b0(k3); + b1 = (TwoFish_P[TwoFish_P_14][b1]) ^ TwoFish_b1(k3); + b2 = (TwoFish_P[TwoFish_P_24][b2]) ^ TwoFish_b2(k3); + b3 = (TwoFish_P[TwoFish_P_34][b3]) ^ TwoFish_b3(k3); + case 3: /* 192-bit keys */ + b0 = (TwoFish_P[TwoFish_P_03][b0]) ^ TwoFish_b0(k2); + b1 = (TwoFish_P[TwoFish_P_13][b1]) ^ TwoFish_b1(k2); + b2 = (TwoFish_P[TwoFish_P_23][b2]) ^ TwoFish_b2(k2); + b3 = (TwoFish_P[TwoFish_P_33][b3]) ^ TwoFish_b3(k2); + case 2: /* 128-bit keys */ + tfdata->sBox[ 2*i ]= + TwoFish_MDS[0][(TwoFish_P[TwoFish_P_01][(TwoFish_P[TwoFish_P_02][b0]) ^ + TwoFish_b0(k1)]) ^ TwoFish_b0(k0)]; + + tfdata->sBox[ 2*i+1]= + TwoFish_MDS[1][(TwoFish_P[TwoFish_P_11][(TwoFish_P[TwoFish_P_12][b1]) ^ + TwoFish_b1(k1)]) ^ TwoFish_b1(k0)]; + + tfdata->sBox[0x200+2*i ]= + TwoFish_MDS[2][(TwoFish_P[TwoFish_P_21][(TwoFish_P[TwoFish_P_22][b2]) ^ + TwoFish_b2(k1)]) ^ TwoFish_b2(k0)]; + + tfdata->sBox[0x200+2*i+1]= + TwoFish_MDS[3][(TwoFish_P[TwoFish_P_31][(TwoFish_P[TwoFish_P_32][b3]) ^ + TwoFish_b3(k1)]) ^ TwoFish_b3(k0)]; + } + } +} + + +/** + * Encrypt or decrypt exactly one block of plaintext in CBC mode. + * Use "ciphertext stealing" technique described on pg. 196 + * of "Applied Cryptography" to encrypt the final partial + * (i.e. <16 byte) block if necessary. + * + * jojo: the "ciphertext stealing" requires we read ahead and have + * special handling for the last two blocks. Because of this, the + * output from the TwoFish algorithm is handled internally here. + * It would be better to have a higher level handle this as well as + * CBC mode. Unfortunately, I've mixed the two together, which is + * pretty crappy... The Java version separates these out correctly. + * + * fknobbe: I have reduced the CBC mode to work on memory buffer only. + * Higher routines should use an intermediate buffer and handle + * their output seperately (mainly so the data can be flushed + * in one chunk, not seperate 16 byte blocks...) + * + * @param in The plaintext. + * @param out The ciphertext + * @param size how much to encrypt + * @param tfdata: Pointer to the global data structure containing session keys. + * @return none + */ +void _TwoFish_BlockCrypt(u_int8_t *in,u_int8_t *out,u_int32_t size,int decrypt,TWOFISH *tfdata) +{ u_int8_t PnMinusOne[TwoFish_BLOCK_SIZE]; + u_int8_t CnMinusOne[TwoFish_BLOCK_SIZE]; + u_int8_t CBCplusCprime[TwoFish_BLOCK_SIZE]; + u_int8_t Pn[TwoFish_BLOCK_SIZE]; + u_int8_t *p,*pout; + u_int32_t i; + + /* here is where we implement CBC mode and cipher block stealing */ + if(size==TwoFish_BLOCK_SIZE) + { /* if we are encrypting, CBC means we XOR the plain text block with the */ + /* previous cipher text block before encrypting */ + if(!decrypt && tfdata->qBlockDefined) + { for(p=in,i=0;iqBlockCrypt[i]; /* FK: I'm copying the xor'ed input into Pn... */ + } + else + memcpy(Pn,in,TwoFish_BLOCK_SIZE); /* FK: same here. we work of Pn all the time. */ + + /* TwoFish block level encryption or decryption */ + _TwoFish_BlockCrypt16(Pn,out,decrypt,tfdata); + + /* if we are decrypting, CBC means we XOR the result of the decryption */ + /* with the previous cipher text block to get the resulting plain text */ + if(decrypt && tfdata->qBlockDefined) + { for (p=out,i=0;iqBlockPlain[i]; + } + + /* save the input and output blocks, since CBC needs these for XOR */ + /* operations */ + _TwoFish_qBlockPush(Pn,out,tfdata); + } + else + { /* cipher block stealing, we are at Pn, */ + /* but since Cn-1 must now be replaced with CnC' */ + /* we pop it off, and recalculate Cn-1 */ + + if(decrypt) + { /* We are on an odd block, and had to do cipher block stealing, */ + /* so the PnMinusOne has to be derived differently. */ + + /* First we decrypt it into CBC and C' */ + _TwoFish_qBlockPop(CnMinusOne,PnMinusOne,tfdata); + _TwoFish_BlockCrypt16(CnMinusOne,CBCplusCprime,decrypt,tfdata); + + /* we then xor the first few bytes with the "in" bytes (Cn) */ + /* to recover Pn, which we put in out */ + for(p=in,pout=out,i=0;iprevCipher[i]; + + /* So at this point, out has PnMinusOne */ + _TwoFish_qBlockPush(CnMinusOne,PnMinusOne,tfdata); + _TwoFish_FlushOutput(tfdata->qBlockCrypt,TwoFish_BLOCK_SIZE,tfdata); + _TwoFish_FlushOutput(out,size,tfdata); + } + else + { _TwoFish_qBlockPop(PnMinusOne,CnMinusOne,tfdata); + memset(Pn,0,TwoFish_BLOCK_SIZE); + memcpy(Pn,in,size); + for(i=0;iqBlockCrypt,TwoFish_BLOCK_SIZE,tfdata); + _TwoFish_FlushOutput(CnMinusOne,size,tfdata); /* old Cn-1 becomes new partial Cn */ + } + tfdata->qBlockDefined=FALSE; + } +} + +void _TwoFish_qBlockPush(u_int8_t *p,u_int8_t *c,TWOFISH *tfdata) +{ if(tfdata->qBlockDefined) + _TwoFish_FlushOutput(tfdata->qBlockCrypt,TwoFish_BLOCK_SIZE,tfdata); + memcpy(tfdata->prevCipher,tfdata->qBlockPlain,TwoFish_BLOCK_SIZE); + memcpy(tfdata->qBlockPlain,p,TwoFish_BLOCK_SIZE); + memcpy(tfdata->qBlockCrypt,c,TwoFish_BLOCK_SIZE); + tfdata->qBlockDefined=TRUE; +} + +void _TwoFish_qBlockPop(u_int8_t *p,u_int8_t *c,TWOFISH *tfdata) +{ memcpy(p,tfdata->qBlockPlain,TwoFish_BLOCK_SIZE ); + memcpy(c,tfdata->qBlockCrypt,TwoFish_BLOCK_SIZE ); + tfdata->qBlockDefined=FALSE; +} + +/* Reset's the CBC flag and zero's PrevCipher (through qBlockPlain) (important) */ +void _TwoFish_ResetCBC(TWOFISH *tfdata) +{ tfdata->qBlockDefined=FALSE; + memset(tfdata->qBlockPlain,0,TwoFish_BLOCK_SIZE); +} + +void _TwoFish_FlushOutput(u_int8_t *b,u_int32_t len,TWOFISH *tfdata) +{ u_int32_t i; + + for(i=0;idontflush;i++) + *tfdata->output++ = *b++; + tfdata->dontflush=FALSE; +} + +void _TwoFish_BlockCrypt16(u_int8_t *in,u_int8_t *out,bool decrypt,TWOFISH *tfdata) +{ u_int32_t x0,x1,x2,x3; + u_int32_t k,t0,t1,R; + + + x0=*in++; + x0|=(*in++ << 8 ); + x0|=(*in++ << 16); + x0|=(*in++ << 24); + x1=*in++; + x1|=(*in++ << 8 ); + x1|=(*in++ << 16); + x1|=(*in++ << 24); + x2=*in++; + x2|=(*in++ << 8 ); + x2|=(*in++ << 16); + x2|=(*in++ << 24); + x3=*in++; + x3|=(*in++ << 8 ); + x3|=(*in++ << 16); + x3|=(*in++ << 24); + + if(decrypt) + { x0 ^= tfdata->subKeys[4]; /* swap input and output whitening keys when decrypting */ + x1 ^= tfdata->subKeys[5]; + x2 ^= tfdata->subKeys[6]; + x3 ^= tfdata->subKeys[7]; + + k = 7+(TwoFish_ROUNDS*2); + for (R = 0; R < TwoFish_ROUNDS; R += 2) + { t0 = _TwoFish_Fe320( tfdata->sBox, x0); + t1 = _TwoFish_Fe323( tfdata->sBox, x1); + x3 ^= t0 + (t1<<1) + tfdata->subKeys[k--]; + x3 = x3 >> 1 | x3 << 31; + x2 = x2 << 1 | x2 >> 31; + x2 ^= t0 + t1 + tfdata->subKeys[k--]; + + t0 = _TwoFish_Fe320( tfdata->sBox, x2); + t1 = _TwoFish_Fe323( tfdata->sBox, x3); + x1 ^= t0 + (t1<<1) + tfdata->subKeys[k--]; + x1 = x1 >> 1 | x1 << 31; + x0 = x0 << 1 | x0 >> 31; + x0 ^= t0 + t1 + tfdata->subKeys[k--]; + } + + x2 ^= tfdata->subKeys[0]; + x3 ^= tfdata->subKeys[1]; + x0 ^= tfdata->subKeys[2]; + x1 ^= tfdata->subKeys[3]; + } + else + { x0 ^= tfdata->subKeys[0]; + x1 ^= tfdata->subKeys[1]; + x2 ^= tfdata->subKeys[2]; + x3 ^= tfdata->subKeys[3]; + + k = 8; + for (R = 0; R < TwoFish_ROUNDS; R += 2) + { t0 = _TwoFish_Fe320( tfdata->sBox, x0); + t1 = _TwoFish_Fe323( tfdata->sBox, x1); + x2 ^= t0 + t1 + tfdata->subKeys[k++]; + x2 = x2 >> 1 | x2 << 31; + x3 = x3 << 1 | x3 >> 31; + x3 ^= t0 + (t1<<1) + tfdata->subKeys[k++]; + + t0 = _TwoFish_Fe320( tfdata->sBox, x2); + t1 = _TwoFish_Fe323( tfdata->sBox, x3); + x0 ^= t0 + t1 + tfdata->subKeys[k++]; + x0 = x0 >> 1 | x0 << 31; + x1 = x1 << 1 | x1 >> 31; + x1 ^= t0 + (t1<<1) + tfdata->subKeys[k++]; + } + + x2 ^= tfdata->subKeys[4]; + x3 ^= tfdata->subKeys[5]; + x0 ^= tfdata->subKeys[6]; + x1 ^= tfdata->subKeys[7]; + } + + *out++ = (u_int8_t)(x2 ); + *out++ = (u_int8_t)(x2 >> 8); + *out++ = (u_int8_t)(x2 >> 16); + *out++ = (u_int8_t)(x2 >> 24); + + *out++ = (u_int8_t)(x3 ); + *out++ = (u_int8_t)(x3 >> 8); + *out++ = (u_int8_t)(x3 >> 16); + *out++ = (u_int8_t)(x3 >> 24); + + *out++ = (u_int8_t)(x0 ); + *out++ = (u_int8_t)(x0 >> 8); + *out++ = (u_int8_t)(x0 >> 16); + *out++ = (u_int8_t)(x0 >> 24); + + *out++ = (u_int8_t)(x1 ); + *out++ = (u_int8_t)(x1 >> 8); + *out++ = (u_int8_t)(x1 >> 16); + *out++ = (u_int8_t)(x1 >> 24); +} + +/** + * Use (12, 8) Reed-Solomon code over GF(256) to produce a key S-box + * 32-bit entity from two key material 32-bit entities. + * + * @param k0 1st 32-bit entity. + * @param k1 2nd 32-bit entity. + * @return Remainder polynomial generated using RS code + */ +u_int32_t _TwoFish_RS_MDS_Encode(u_int32_t k0,u_int32_t k1) +{ u_int32_t i,r; + + for(r=k1,i=0;i<4;i++) /* shift 1 byte at a time */ + TwoFish_RS_rem(r); + r ^= k0; + for(i=0;i<4;i++) + TwoFish_RS_rem(r); + + return r; +} + +u_int32_t _TwoFish_F32(u_int32_t k64Cnt,u_int32_t x,u_int32_t *k32) +{ u_int8_t b0,b1,b2,b3; + u_int32_t k0,k1,k2,k3,result = 0; + + b0=TwoFish_b0(x); + b1=TwoFish_b1(x); + b2=TwoFish_b2(x); + b3=TwoFish_b3(x); + k0=k32[0]; + k1=k32[1]; + k2=k32[2]; + k3=k32[3]; + + switch (k64Cnt & 3) + { case 1: /* 64-bit keys */ + result = + TwoFish_MDS[0][(TwoFish_P[TwoFish_P_01][b0] & 0xFF) ^ TwoFish_b0(k0)] ^ + TwoFish_MDS[1][(TwoFish_P[TwoFish_P_11][b1] & 0xFF) ^ TwoFish_b1(k0)] ^ + TwoFish_MDS[2][(TwoFish_P[TwoFish_P_21][b2] & 0xFF) ^ TwoFish_b2(k0)] ^ + TwoFish_MDS[3][(TwoFish_P[TwoFish_P_31][b3] & 0xFF) ^ TwoFish_b3(k0)]; + break; + case 0: /* 256-bit keys (same as 4) */ + b0 = (TwoFish_P[TwoFish_P_04][b0] & 0xFF) ^ TwoFish_b0(k3); + b1 = (TwoFish_P[TwoFish_P_14][b1] & 0xFF) ^ TwoFish_b1(k3); + b2 = (TwoFish_P[TwoFish_P_24][b2] & 0xFF) ^ TwoFish_b2(k3); + b3 = (TwoFish_P[TwoFish_P_34][b3] & 0xFF) ^ TwoFish_b3(k3); + + case 3: /* 192-bit keys */ + b0 = (TwoFish_P[TwoFish_P_03][b0] & 0xFF) ^ TwoFish_b0(k2); + b1 = (TwoFish_P[TwoFish_P_13][b1] & 0xFF) ^ TwoFish_b1(k2); + b2 = (TwoFish_P[TwoFish_P_23][b2] & 0xFF) ^ TwoFish_b2(k2); + b3 = (TwoFish_P[TwoFish_P_33][b3] & 0xFF) ^ TwoFish_b3(k2); + case 2: /* 128-bit keys (optimize for this case) */ + result = + TwoFish_MDS[0][(TwoFish_P[TwoFish_P_01][(TwoFish_P[TwoFish_P_02][b0] & 0xFF) ^ TwoFish_b0(k1)] & 0xFF) ^ TwoFish_b0(k0)] ^ + TwoFish_MDS[1][(TwoFish_P[TwoFish_P_11][(TwoFish_P[TwoFish_P_12][b1] & 0xFF) ^ TwoFish_b1(k1)] & 0xFF) ^ TwoFish_b1(k0)] ^ + TwoFish_MDS[2][(TwoFish_P[TwoFish_P_21][(TwoFish_P[TwoFish_P_22][b2] & 0xFF) ^ TwoFish_b2(k1)] & 0xFF) ^ TwoFish_b2(k0)] ^ + TwoFish_MDS[3][(TwoFish_P[TwoFish_P_31][(TwoFish_P[TwoFish_P_32][b3] & 0xFF) ^ TwoFish_b3(k1)] & 0xFF) ^ TwoFish_b3(k0)]; + break; + } + return result; +} + +u_int32_t _TwoFish_Fe320(u_int32_t *lsBox,u_int32_t x) +{ return lsBox[ TwoFish_b0(x)<<1 ]^ + lsBox[ ((TwoFish_b1(x)<<1)|1)]^ + lsBox[0x200+ (TwoFish_b2(x)<<1) ]^ + lsBox[0x200+((TwoFish_b3(x)<<1)|1)]; +} + +u_int32_t _TwoFish_Fe323(u_int32_t *lsBox,u_int32_t x) +{ return lsBox[ (TwoFish_b3(x)<<1) ]^ + lsBox[ ((TwoFish_b0(x)<<1)|1)]^ + lsBox[0x200+ (TwoFish_b1(x)<<1) ]^ + lsBox[0x200+((TwoFish_b2(x)<<1)|1)]; +} + +u_int32_t _TwoFish_Fe32(u_int32_t *lsBox,u_int32_t x,u_int32_t R) +{ return lsBox[ 2*TwoFish__b(x,R ) ]^ + lsBox[ 2*TwoFish__b(x,R+1)+1]^ + lsBox[0x200+2*TwoFish__b(x,R+2) ]^ + lsBox[0x200+2*TwoFish__b(x,R+3)+1]; +} + + +#endif + +/* ******************************************* */ +#if defined TWOFISH_UNIT_TEST +#include + +#define TEST_DATA_SIZE 327 + +int main(int argc, char* argv[]) +{ + int i; + int n; + + char outbuf[4096]; + char * outp = outbuf; + + u_int8_t key[] = { 0xfc, 0x77, 0x1a, 0xda, 0xaa }; + TWOFISH *tfa = TwoFishInit( key, 5 ); + TWOFISH *tfb = TwoFishInit( key, 5 ); + + u_int8_t out[2048], out2[2048]; + u_int8_t in[TEST_DATA_SIZE]; + + for ( i=0; i: + * --- April 2001, converted from C++ to C, prefixed global variables + * with TwoFish, substituted some defines, changed functions to make use of + * variables supplied in a struct, modified and added routines for modular calls. + * Cleaned up the code so that defines are used instead of fixed 16's and 32's. + * Created two general purpose crypt routines for one block and multiple block + * encryption using Joh's CBC code. + * Added crypt routines that use a header (with a magic and data length). + * (Basically a major rewrite). + * + * Note: Routines labeled _TwoFish are private and should not be used + * (or with extreme caution). + * + */ + +#ifndef __TWOFISH_LIBRARY_HEADER__ +#define __TWOFISH_LIBRARY_HEADER__ + +#ifndef FALSE +#define FALSE 0 +#endif +#ifndef TRUE +#define TRUE !FALSE +#endif +#ifndef bool +#define bool int +#endif + +#ifdef WIN32 +#include "win32/n2n_win32.h" +#endif + +/* Constants */ + +#define TwoFish_DEFAULT_PW "SnortHas2FishEncryptionRoutines!" /* default password (not more than 32 chars) */ +#define TwoFish_DEFAULT_PW_LEN 32 +#define TwoFish_MAGIC "TwoFish" /* to indentify a successful decryption */ + +enum +{ TwoFish_KEY_SIZE = 256, /* Valid values: 64, 128, 192, 256 */ + /* User 256, other key sizes have not been tested. */ + /* (But should work. I substitutes as much as */ + /* I could with this define.) */ + TwoFish_ROUNDS = 16, + TwoFish_BLOCK_SIZE = 16, /* bytes in a data-block */ + TwoFish_KEY_LENGTH = TwoFish_KEY_SIZE/8, /* 32= 256-bit key */ + TwoFish_TOTAL_SUBKEYS = 4+4+2*TwoFish_ROUNDS, + TwoFish_MAGIC_LEN = TwoFish_BLOCK_SIZE-8, + TwoFish_SK_BUMP = 0x01010101, + TwoFish_SK_ROTL = 9, + TwoFish_P_00 = 1, + TwoFish_P_01 = 0, + TwoFish_P_02 = 0, + TwoFish_P_03 = TwoFish_P_01 ^ 1, + TwoFish_P_04 = 1, + TwoFish_P_10 = 0, + TwoFish_P_11 = 0, + TwoFish_P_12 = 1, + TwoFish_P_13 = TwoFish_P_11 ^ 1, + TwoFish_P_14 = 0, + TwoFish_P_20 = 1, + TwoFish_P_21 = 1, + TwoFish_P_22 = 0, + TwoFish_P_23 = TwoFish_P_21 ^ 1, + TwoFish_P_24 = 0, + TwoFish_P_30 = 0, + TwoFish_P_31 = 1, + TwoFish_P_32 = 1, + TwoFish_P_33 = TwoFish_P_31 ^ 1, + TwoFish_P_34 = 1, + TwoFish_GF256_FDBK = 0x169, + TwoFish_GF256_FDBK_2 = 0x169 / 2, + TwoFish_GF256_FDBK_4 = 0x169 / 4, + TwoFish_RS_GF_FDBK = 0x14D, /* field generator */ + TwoFish_MDS_GF_FDBK = 0x169 /* primitive polynomial for GF(256) */ +}; + + +/* Global data structure for callers */ + +typedef struct +{ + u_int32_t sBox[4 * 256]; /* Key dependent S-box */ + u_int32_t subKeys[TwoFish_TOTAL_SUBKEYS]; /* Subkeys */ + u_int8_t key[TwoFish_KEY_LENGTH]; /* Encryption Key */ + u_int8_t *output; /* Pointer to output buffer */ + u_int8_t qBlockPlain[TwoFish_BLOCK_SIZE]; /* Used by CBC */ + u_int8_t qBlockCrypt[TwoFish_BLOCK_SIZE]; + u_int8_t prevCipher[TwoFish_BLOCK_SIZE]; + struct /* Header for crypt functions. Has to be at least one block long. */ + { u_int32_t salt; /* Random salt in first block (will salt the rest through CBC) */ + u_int8_t length[4]; /* The amount of data following the header */ + u_int8_t magic[TwoFish_MAGIC_LEN]; /* Magic to identify successful decryption */ + } header; + bool qBlockDefined; + bool dontflush; +} TWOFISH; + +#ifndef __TWOFISH_LIBRARY_SOURCE__ + +extern bool TwoFish_srand; /* if set to TRUE (default), first call of TwoFishInit will seed rand(); */ + /* call of TwoFishInit */ +#endif + + +/**** Public Functions ****/ + +/* TwoFish Initialization + * + * This routine generates a global data structure for use with TwoFish, + * initializes important values (such as subkeys, sBoxes), generates subkeys + * and precomputes the MDS matrix if not already done. + * + * Input: User supplied password (will be appended by default password of 'SnortHas2FishEncryptionRoutines!') + * + * Output: Pointer to TWOFISH structure. This data structure contains key dependent data. + * This pointer is used with all other crypt functions. + */ +TWOFISH *TwoFishInit(const u_int8_t *userkey, u_int32_t keysize ); + + +/* TwoFish Destroy + * + * Nothing else but a free... + * + * Input: Pointer to the TwoFish structure. + * + */ +void TwoFishDestroy(TWOFISH *tfdata); + + +/* TwoFish Alloc + * + * Allocates enough memory for the output buffer as required. + * + * Input: Length of the plaintext. + * Boolean flag for BinHex Output. + * Pointer to the TwoFish structure. + * + * Output: Returns a pointer to the memory allocated. + */ +void *TwoFishAlloc(u_int32_t len,bool binhex,bool decrypt,TWOFISH *tfdata); + + +/* TwoFish Free + * + * Free's the allocated buffer. + * + * Input: Pointer to the TwoFish structure + * + * Output: (none) + */ +void TwoFishFree(TWOFISH *tfdata); + + +/* TwoFish Set Output + * + * If you want to allocate the output buffer yourself, + * then you can set it with this function. + * + * Input: Pointer to your output buffer + * Pointer to the TwoFish structure + * + * Output: (none) + */ +void TwoFishSetOutput(u_int8_t *outp,TWOFISH *tfdata); + + +/* TwoFish Raw Encryption + * + * Does not use header, but does use CBC (if more than one block has to be encrypted). + * + * Input: Pointer to the buffer of the plaintext to be encrypted. + * Pointer to the buffer receiving the ciphertext. + * The length of the plaintext buffer. + * The TwoFish structure. + * + * Output: The amount of bytes encrypted if successful, otherwise 0. + */ +u_int32_t TwoFishEncryptRaw(u_int8_t *in,u_int8_t *out,u_int32_t len,TWOFISH *tfdata); + +/* TwoFish Raw Decryption + * + * Does not use header, but does use CBC (if more than one block has to be decrypted). + * + * Input: Pointer to the buffer of the ciphertext to be decrypted. + * Pointer to the buffer receiving the plaintext. + * The length of the ciphertext buffer (at least one cipher block). + * The TwoFish structure. + * + * Output: The amount of bytes decrypted if successful, otherwise 0. + */ +u_int32_t TwoFishDecryptRaw(u_int8_t *in,u_int8_t *out,u_int32_t len,TWOFISH *tfdata); + + +/* TwoFish Encryption + * + * Uses header and CBC. If the output area has not been intialized with TwoFishAlloc, + * this routine will alloc the memory. In addition, it will include a small 'header' + * containing the magic and some salt. That way the decrypt routine can check if the + * packet got decrypted successfully, and return 0 instead of garbage. + * + * Input: Pointer to the buffer of the plaintext to be encrypted. + * Pointer to the pointer to the buffer receiving the ciphertext. + * The pointer either points to user allocated output buffer space, or to NULL, in which case + * this routine will set the pointer to the buffer allocated through the struct. + * The length of the plaintext buffer. + * Can be -1 if the input is a null terminated string, in which case we'll count for you. + * Boolean flag for BinHex Output (if used, output will be twice as large as input). + * Note: BinHex conversion overwrites (converts) input buffer! + * The TwoFish structure. + * + * Output: The amount of bytes encrypted if successful, otherwise 0. + */ +u_int32_t TwoFishEncrypt(u_int8_t *in,u_int8_t **out,signed long len,bool binhex,TWOFISH *tfdata); + + +/* TwoFish Decryption + * + * Uses header and CBC. If the output area has not been intialized with TwoFishAlloc, + * this routine will alloc the memory. In addition, it will check the small 'header' + * containing the magic. If magic does not match we return 0. Otherwise we return the + * amount of bytes decrypted (should be the same as the length in the header). + * + * Input: Pointer to the buffer of the ciphertext to be decrypted. + * Pointer to the pointer to the buffer receiving the plaintext. + * The pointer either points to user allocated output buffer space, or to NULL, in which case + * this routine will set the pointer to the buffer allocated through the struct. + * The length of the ciphertext buffer. + * Can be -1 if the input is a null terminated binhex string, in which case we'll count for you. + * Boolean flag for BinHex Input (if used, plaintext will be half as large as input). + * Note: BinHex conversion overwrites (converts) input buffer! + * The TwoFish structure. + * + * Output: The amount of bytes decrypted if successful, otherwise 0. + */ +u_int32_t TwoFishDecrypt(u_int8_t *in,u_int8_t **out,signed long len,bool binhex,TWOFISH *tfdata); + + +/**** Private Functions ****/ + +u_int8_t TwoFish__b(u_int32_t x,int n); +void _TwoFish_BinHex(u_int8_t *buf,u_int32_t len,bool bintohex); +u_int32_t _TwoFish_CryptRawCBC(u_int8_t *in,u_int8_t *out,u_int32_t len,bool decrypt,TWOFISH *tfdata); +u_int32_t _TwoFish_CryptRaw16(u_int8_t *in,u_int8_t *out,u_int32_t len,bool decrypt,TWOFISH *tfdata); +u_int32_t _TwoFish_CryptRaw(u_int8_t *in,u_int8_t *out,u_int32_t len,bool decrypt,TWOFISH *tfdata); +void _TwoFish_PrecomputeMDSmatrix(void); +void _TwoFish_MakeSubKeys(TWOFISH *tfdata); +void _TwoFish_qBlockPush(u_int8_t *p,u_int8_t *c,TWOFISH *tfdata); +void _TwoFish_qBlockPop(u_int8_t *p,u_int8_t *c,TWOFISH *tfdata); +void _TwoFish_ResetCBC(TWOFISH *tfdata); +void _TwoFish_FlushOutput(u_int8_t *b,u_int32_t len,TWOFISH *tfdata); +void _TwoFish_BlockCrypt(u_int8_t *in,u_int8_t *out,u_int32_t size,int decrypt,TWOFISH *tfdata); +void _TwoFish_BlockCrypt16(u_int8_t *in,u_int8_t *out,bool decrypt,TWOFISH *tfdata); +u_int32_t _TwoFish_RS_MDS_Encode(u_int32_t k0,u_int32_t k1); +u_int32_t _TwoFish_F32(u_int32_t k64Cnt,u_int32_t x,u_int32_t *k32); +u_int32_t _TwoFish_Fe320(u_int32_t *lsBox,u_int32_t x); +u_int32_t _TwoFish_Fe323(u_int32_t *lsBox,u_int32_t x); +u_int32_t _TwoFish_Fe32(u_int32_t *lsBox,u_int32_t x,u_int32_t R); + + +#endif