pax_global_header00006660000000000000000000000064150045425210014510gustar00rootroot0000000000000052 comment=773e1fb7b5a0cfc89d1b88f0aeebfc3fcc71e8c3 opengnb-ver1.6.0.a/000077500000000000000000000000001500454252100141005ustar00rootroot00000000000000opengnb-ver1.6.0.a/.gitattributes000066400000000000000000000000311500454252100167650ustar00rootroot00000000000000*.sh linguist-language=c opengnb-ver1.6.0.a/.gitignore000066400000000000000000000007011500454252100160660ustar00rootroot00000000000000# Prerequisites *.d # Object files *.o *.ko *.obj *.elf # Linker output *.ilk *.map *.exp # Precompiled Headers *.gch *.pch # Libraries *.lib *.a *.la *.lo # Shared objects (inc. Windows DLLs) *.dll *.so *.so.* *.dylib # Executables #*.exe *.out *.app *.i*86 *.x86_64 *.hex # Debug files *.dSYM/ *.su *.idb *.pdb # Kernel Module Compile Results *.mod* #*.cmd .tmp_versions/ modules.order Module.symvers Mkfile.old dkms.conf #vscode .vscode opengnb-ver1.6.0.a/LICENSE000066400000000000000000001045151500454252100151130ustar00rootroot00000000000000 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: Copyright (C) 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 . opengnb-ver1.6.0.a/Makefile.Darwin000066400000000000000000000031171500454252100167650ustar00rootroot00000000000000CFLAGS=-O2 -I./src -I./libs -I./libs/miniupnpc -I./libs/libnatpmp -I./libs/zlib -D NO_GZIP=1 -Wno-deprecated-non-prototype #-D Z_SOLO=0 CLI_LDFLAGS=-L/usr/lib -pthread GNB_ES_LDFLAGS=-L/usr/lib -pthread GNB_CRYPTO=gnb_crypto GNB_CTL=gnb_ctl GNB_ES=gnb_es GNB_CLI=gnb include Makefile.inc GNB_CLI_OBJS = \ ./src/cli/gnb.o \ ./src/gnb_argv.o \ ./src/unix/unix_platform.o \ ./src/Darwin/gnb_drv_darwin.o GNB_ES_OBJS += ./src/unix/unix_platform.o all:${GNB_CLI} ${GNB_CRYPTO} ${GNB_ES} ${GNB_CTL} ${GNB_CTL}: ${GNB_CTL_OBJS} ${CC} -o ${GNB_CTL} ${GNB_CTL_OBJS} ${CLI_LDFLAGS} strip ${GNB_CTL} ${GNB_ES}: ${GNB_ES_OBJS} ${CRYPTO_OBJS} ${MINIUPNP_OBJS} ${LIBNATPMP_OBJS} ${CC} -o ${GNB_ES} ${GNB_ES_OBJS} ${CRYPTO_OBJS} ${MINIUPNP_OBJS} ${LIBNATPMP_OBJS} ${GNB_ES_LDFLAGS} strip ${GNB_ES} ${GNB_CRYPTO}: ${CRYPTO_OBJS} ./src/cli/gnb_crypto.o ${CC} -o ${GNB_CRYPTO} ./src/cli/gnb_crypto.o ${CRYPTO_OBJS} ${CLI_LDFLAGS} strip ${GNB_CRYPTO} ${GNB_CLI}: ${GNB_OBJS} ${GNB_CLI_OBJS} ${GNB_PF_OBJS} ${CRYPTO_OBJS} ${ZLIB_OBJS} ${CC} -o ${GNB_CLI} ${GNB_OBJS} ${GNB_CLI_OBJS} ${GNB_PF_OBJS} ${CRYPTO_OBJS} ${ZLIB_OBJS} ${CLI_LDFLAGS} strip ${GNB_CLI} %.o:%.c ${CC} ${CFLAGS} -c -o $@ $< install:${GNB_CLI} ${GNB_CRYPTO} ${GNB_ES} ${GNB_CTL} mkdir -p ./bin/ cp ${GNB_CLI} ./bin/ cp ${GNB_CTL} ./bin/ cp ${GNB_CRYPTO} ./bin/ cp ${GNB_ES} ./bin/ clean: find . -name "*.o" -exec rm -f {} \; rm -f ${GNB_CLI} ${GNB_CRYPTO} ${GNB_ES} ${GNB_CTL} rm -f core rm -f *.exe opengnb-ver1.6.0.a/Makefile.freebsd000066400000000000000000000030661500454252100171560ustar00rootroot00000000000000CFLAGS=-O2 -I./src -I./libs -I./libs/miniupnpc -I./libs/libnatpmp -I./libs/zlib -D NO_GZIP=1 CLI_LDFLAGS=-s -L/usr/lib -pthread GNB_ES_LDFLAGS=-s -L/usr/lib -pthread ifeq ($(DEBUG),1) CFLAGS += -g else CLI_LDFLAGS += -s GNB_ES_LDFLAGS += -s endif GNB_CRYPTO=gnb_crypto GNB_CTL=gnb_ctl GNB_ES=gnb_es GNB_CLI=gnb include Makefile.inc GNB_CLI_OBJS = \ ./src/cli/gnb.o \ ./src/gnb_argv.o \ ./src/unix/unix_platform.o \ ./src/freebsd/gnb_drv_freebsd.o GNB_ES_OBJS += ./src/unix/unix_platform.o all:${GNB_CLI} ${GNB_CRYPTO} ${GNB_ES} ${GNB_CTL} $(GNB_CTL): $(GNB_CTL_OBJS) ${CC} -o ${GNB_CTL} ${GNB_CTL_OBJS} ${CLI_LDFLAGS} $(GNB_ES): $(GNB_ES_OBJS) ${CRYPTO_OBJS} ${MINIUPNP_OBJS} ${LIBNATPMP_OBJS} ${CC} -o ${GNB_ES} ${GNB_ES_OBJS} ${CRYPTO_OBJS} ${MINIUPNP_OBJS} ${LIBNATPMP_OBJS} ${GNB_ES_LDFLAGS} $(GNB_CRYPTO): $(CRYPTO_OBJS) ./src/cli/gnb_crypto.o ${CC} -o ${GNB_CRYPTO} ./src/cli/gnb_crypto.o ${CRYPTO_OBJS} ${CLI_LDFLAGS} $(GNB_CLI): $(GNB_OBJS) $(GNB_CLI_OBJS) $(GNB_PF_OBJS) ${CRYPTO_OBJS} ${ZLIB_OBJS} ${CC} -o ${GNB_CLI} ${GNB_OBJS} ${GNB_CLI_OBJS} ${GNB_PF_OBJS} ${CRYPTO_OBJS} ${ZLIB_OBJS} ${CLI_LDFLAGS} %.o:%.c ${CC} ${CFLAGS} -c -o $@ $< install:${GNB_CLI} ${GNB_CRYPTO} ${GNB_ES} ${GNB_CTL} mkdir -p ./bin/ cp ${GNB_CLI} ./bin/ cp ${GNB_CTL} ./bin/ cp ${GNB_CRYPTO} ./bin/ cp ${GNB_ES} ./bin/ clean: find . -name "*.o" -exec rm -f {} \; rm -f ${GNB_CLI} ${GNB_CRYPTO} ${GNB_ES} ${GNB_CTL} rm -f core rm -f *.exe opengnb-ver1.6.0.a/Makefile.inc000066400000000000000000000136361500454252100163210ustar00rootroot00000000000000MINIUPNP_OBJS = \ ./libs/miniupnpc/miniwget.o \ ./libs/miniupnpc/minixml.o \ ./libs/miniupnpc/igd_desc_parse.o \ ./libs/miniupnpc/minisoap.o \ ./libs/miniupnpc/miniupnpc.o \ ./libs/miniupnpc/upnpreplyparse.o \ ./libs/miniupnpc/upnpcommands.o \ ./libs/miniupnpc/upnperrors.o \ ./libs/miniupnpc/connecthostport.o \ ./libs/miniupnpc/portlistingparse.o \ ./libs/miniupnpc/receivedata.o \ ./libs/miniupnpc/upnpdev.o \ ./libs/miniupnpc/minissdpc.o LIBNATPMP_OBJS = \ ./libs/libnatpmp/natpmp.o \ ./libs/libnatpmp/getgateway.o \ ./libs/libnatpmp/wingettimeofday.o \ ZLIB_OBJS = \ ./libs/zlib/adler32.o \ ./libs/zlib/deflate.o \ ./libs/zlib/inffast.o \ ./libs/zlib/inflate.o \ ./libs/zlib/inftrees.o \ ./libs/zlib/trees.o \ ./libs/zlib/zutil.o CRYPTO_OBJS = \ ./libs/ed25519/add_scalar.o \ ./libs/ed25519/fe.o \ ./libs/ed25519/ge.o \ ./libs/ed25519/key_exchange.o \ ./libs/ed25519/keypair.o \ ./libs/ed25519/sc.o \ ./libs/ed25519/seed.o \ ./libs/ed25519/sha512.o \ ./libs/ed25519/sign.o \ ./libs/ed25519/verify.o \ ./src/gnb_binary.o \ ./src/crypto/arc4/arc4.o \ ./src/crypto/xor/xor.o \ ./src/crypto/random/gnb_random.o GNB_OBJS = \ ./src/gnb_core.o \ ./src/gnb_daemon.o \ ./src/gnb_worker.o \ ./src/gnb_ctl_block.o \ ./src/gnb_address.o \ ./src/gnb_primary_worker.o \ ./src/gnb_pf_worker.o \ ./src/gnb_node_worker.o \ ./src/gnb_index_worker.o \ ./src/gnb_index_service_worker.o \ ./src/gnb_secure_index_worker.o \ ./src/gnb_secure_index_service_worker.o \ ./src/gnb_detect_worker.o \ ./src/gnb_conf.o \ ./src/gnb_conf_file.o \ ./src/gnb_config_lite.o \ ./src/gnb_node.o \ ./src/gnb_udp.o \ ./src/gnb_payload16.o \ ./src/gnb_ring_buffer_fixed.o \ ./src/gnb_time.o \ ./src/gnb_lru32.o \ ./src/gnb_fixed_pool.o \ ./src/gnb_doubly_linked_list.o \ ./src/gnb_alloc.o \ ./src/gnb_mmap.o \ ./src/gnb_dir.o \ ./src/gnb_arg_list.o \ ./src/gnb_log.o \ ./src/gnb_hash32.o \ ./src/gnb_keys.o \ ./src/gnb_nodeid.o \ ./libs/hash/murmurhash.o GNB_PF_OBJS = \ ./src/gnb_pf.o \ ./src/gnb_unified_forwarding.o \ ./src/packet_filter/gnb_pf_route.o \ ./src/packet_filter/gnb_pf_crypto_xor.o \ ./src/packet_filter/gnb_pf_crypto_arc4.o \ ./src/packet_filter/gnb_pf_zip.o \ ./src/packet_filter/gnb_pf_dump.o GNB_ES_OBJS = \ ./src/cli/gnb_es.o \ ./src/es/gnb_environment_service.o \ ./src/gnb_daemon.o \ ./src/es/gnb_es_dump.o \ ./src/es/gnb_es_broadcast_address.o \ ./src/es/gnb_es_resolv.o \ ./src/es/gnb_es_upnp.o \ ./src/es/gnb_discover_in_lan.o \ ./src/gnb_ctl_block.o \ ./src/gnb_time.o \ ./src/gnb_address.o \ ./src/gnb_payload16.o \ ./src/gnb_udp.o \ ./src/gnb_log.o \ ./src/gnb_alloc.o \ ./src/gnb_mmap.o \ ./src/gnb_dir.o \ ./src/gnb_hash32.o \ ./src/gnb_conf.o \ ./src/gnb_arg_list.o \ ./src/gnb_nodeid.o \ ./libs/hash/murmurhash.o GNB_CTL_OBJS = \ ./src/cli/gnb_ctl.o \ ./src/ctl/gnb_ctl_dump.o \ ./src/gnb_ctl_block.o \ ./src/gnb_ctl_block_set.o \ ./src/gnb_binary.o \ ./src/gnb_time.o \ ./src/gnb_address.o \ ./src/gnb_payload16.o \ ./src/gnb_udp.o \ ./src/gnb_mmap.o \ ./src/gnb_nodeid.o \ ./libs/ed25519/sha512.o GNB_OBJS += ./src/gnb_mod_register.o GNB_ES_OBJS += ./src/es/gnb_es_platform.o opengnb-ver1.6.0.a/Makefile.linux000066400000000000000000000032531500454252100167010ustar00rootroot00000000000000CFLAGS=-ffunction-sections -fdata-sections -Wno-unused-result -I./src -I./libs -I./libs/miniupnpc -I./libs/libnatpmp -I./libs/zlib -D NO_GZIP=1 -D GNB_LINUX_BUILD=1 CLI_LDFLAGS=-Wl,--gc-sections -L/usr/lib -pthread GNB_ES_LDFLAGS=-Wl,--gc-sections -L/usr/lib -pthread ifeq ($(DEBUG),1) CFLAGS += -g else CFLAGS += -O2 CLI_LDFLAGS += -s GNB_ES_LDFLAGS += -s endif GNB_CRYPTO=gnb_crypto GNB_CTL=gnb_ctl GNB_ES=gnb_es GNB_CLI=gnb include Makefile.inc GNB_CLI_OBJS = \ ./src/cli/gnb.o \ ./src/gnb_argv.o \ ./src/unix/unix_platform.o \ ./src/linux/gnb_drv_linux.o GNB_ES_OBJS += ./src/unix/unix_platform.o all:${GNB_CLI} ${GNB_CRYPTO} ${GNB_ES} ${GNB_CTL} $(GNB_CTL): $(GNB_CTL_OBJS) ${CC} -o ${GNB_CTL} ${GNB_CTL_OBJS} ${CLI_LDFLAGS} $(GNB_ES): $(GNB_ES_OBJS) ${CRYPTO_OBJS} ${MINIUPNP_OBJS} ${LIBNATPMP_OBJS} ${CC} -o ${GNB_ES} ${GNB_ES_OBJS} ${CRYPTO_OBJS} ${MINIUPNP_OBJS} ${LIBNATPMP_OBJS} ${GNB_ES_LDFLAGS} $(GNB_CRYPTO): $(CRYPTO_OBJS) ./src/cli/gnb_crypto.o ${CC} -o ${GNB_CRYPTO} ./src/cli/gnb_crypto.o ${CRYPTO_OBJS} ${CLI_LDFLAGS} $(GNB_CLI): $(GNB_OBJS) $(GNB_CLI_OBJS) $(GNB_PF_OBJS) ${CRYPTO_OBJS} ${ZLIB_OBJS} ${CC} -o ${GNB_CLI} ${GNB_OBJS} ${GNB_CLI_OBJS} ${GNB_PF_OBJS} ${CRYPTO_OBJS} ${ZLIB_OBJS} ${CLI_LDFLAGS} %.o:%.c ${CC} ${CFLAGS} -c -o $@ $< install:${GNB_CLI} ${GNB_CRYPTO} ${GNB_ES} ${GNB_CTL} mkdir -p ./bin/ cp ${GNB_CLI} ./bin/ cp ${GNB_CTL} ./bin/ cp ${GNB_CRYPTO} ./bin/ cp ${GNB_ES} ./bin/ clean: find . -name "*.o" -exec rm -f {} \; rm -f ${GNB_CLI} ${GNB_CRYPTO} ${GNB_ES} ${GNB_CTL} rm -f core core.* rm -f *.exe opengnb-ver1.6.0.a/Makefile.mingw_x86_64000066400000000000000000000037331500454252100177040ustar00rootroot00000000000000CFLAGS=-O2 -I./src -I/usr/x86_64-w64-mingw32/include -I./libs -I./libs/wintun -I./libs/miniupnpc -I./libs/libnatpmp -I./libs/zlib -D NO_GZIP=1 -DMINIUPNP_STATICLIB -DNATPMP_STATICLIB CLI_LDFLAGS=-s -static -L/usr/x86_64-w64-mingw32/lib/ -lwsock32 -lws2_32 -liphlpapi -lpthread -lmingwex GNB_ES_LDFLAGS=-s -static -L/usr/x86_64-w64-mingw32/lib/ -lwsock32 -lws2_32 -liphlpapi -lpthread -lmingwex GNB_CRYPTO=gnb_crypto.exe GNB_CTL=gnb_ctl.exe GNB_ES=gnb_es.exe GNB_CLI=gnb.exe include Makefile.inc GNB_CLI_OBJS = \ ./src/cli/gnb.o \ ./src/gnb_argv.o \ ./src/mingw/gnb_res.o \ ./src/mingw/windows_platform.o \ ./src/mingw/gnb_drv_win32.o \ ./src/mingw/gnb_drv_wintun.o GNB_ES_OBJS += ./src/mingw/windows_platform.o all:${GNB_CLI} ${GNB_CRYPTO} ${GNB_ES} ${GNB_CTL} ${GNB_CTL}: ${GNB_CTL_OBJS} ./src/mingw/gnb_res.o ${CC} -o ${GNB_CTL} ${GNB_CTL_OBJS} ./src/mingw/gnb_res.o ${CLI_LDFLAGS} ${GNB_ES}: ${GNB_ES_OBJS} ${CRYPTO_OBJS} ${MINIUPNP_OBJS} ${LIBNATPMP_OBJS} ${CC} -o ${GNB_ES} ${GNB_ES_OBJS} ${CRYPTO_OBJS} ${MINIUPNP_OBJS} ${LIBNATPMP_OBJS} ./src/mingw/gnb_res.o ${GNB_ES_LDFLAGS} $(GNB_CRYPTO): $(CRYPTO_OBJS) ./src/cli/gnb_crypto.o ${CC} -o ${GNB_CRYPTO} ./src/cli/gnb_crypto.o ${CRYPTO_OBJS} ${CLI_LDFLAGS} ${GNB_CLI}: ${GNB_OBJS} ${GNB_CLI_OBJS} ${GNB_PF_OBJS} ${CRYPTO_OBJS} ${ZLIB_OBJS} ${CC} -o ${GNB_CLI} ${GNB_OBJS} ${GNB_CLI_OBJS} ${GNB_PF_OBJS} ${CRYPTO_OBJS} ${ZLIB_OBJS} ${CLI_LDFLAGS} %.o:%.c ${CC} ${CFLAGS} -c -o $@ $< ./src/mingw/gnb_res.o: ./src/mingw/gnb_res.rc ${WINDRES} ./src/mingw/gnb_res.rc -o ./src/mingw/gnb_res.o install:${GNB_CLI} ${GNB_CRYPTO} ${GNB_ES} ${GNB_CTL} mkdir -p ./bin/ cp ${GNB_CLI} ./bin/ cp ${GNB_CTL} ./bin/ cp ${GNB_CRYPTO} ./bin/ cp ${GNB_ES} ./bin/ clean: find . -name "*.o" -exec rm -f {} \; rm -f ${GNB_CLI} ${GNB_CRYPTO} ${GNB_ES} ${GNB_CTL} rm -f core rm -f *.exe opengnb-ver1.6.0.a/Makefile.openbsd000066400000000000000000000027371500454252100172020ustar00rootroot00000000000000CFLAGS=-O2 -I./src -I./libs -I./libs/miniupnpc -I./libs/libnatpmp -I./libs/zlib -D NO_GZIP=1 CLI_LDFLAGS=-s -L/usr/lib -pthread GNB_ES_LDFLAGS=-s -L/usr/lib -pthread GNB_CRYPTO=gnb_crypto GNB_CTL=gnb_ctl GNB_ES=gnb_es GNB_CLI=gnb include Makefile.inc GNB_CLI_OBJS = \ ./src/cli/gnb.o \ ./src/gnb_argv.o \ ./src/unix/unix_platform.o \ ./src/openbsd/gnb_drv_openbsd.o GNB_ES_OBJS += ./src/unix/unix_platform.o all:${GNB_CLI} ${GNB_CRYPTO} ${GNB_ES} ${GNB_CTL} $(GNB_CTL): $(GNB_CTL_OBJS) ${CC} -o ${GNB_CTL} ${GNB_CTL_OBJS} ${CLI_LDFLAGS} $(GNB_ES): $(GNB_ES_OBJS) ${CRYPTO_OBJS} ${MINIUPNP_OBJS} ${LIBNATPMP_OBJS} ${CC} -o ${GNB_ES} ${GNB_ES_OBJS} ${CRYPTO_OBJS} ${MINIUPNP_OBJS} ${LIBNATPMP_OBJS} ${GNB_ES_LDFLAGS} $(GNB_CRYPTO): $(CRYPTO_OBJS) ./src/cli/gnb_crypto.o ${CC} -o ${GNB_CRYPTO} ./src/cli/gnb_crypto.o ${CRYPTO_OBJS} ${CLI_LDFLAGS} $(GNB_CLI): $(GNB_OBJS) $(GNB_CLI_OBJS) $(GNB_PF_OBJS) ${CRYPTO_OBJS} ${ZLIB_OBJS} ${CC} -o ${GNB_CLI} ${GNB_OBJS} ${GNB_CLI_OBJS} ${GNB_PF_OBJS} ${CRYPTO_OBJS} ${ZLIB_OBJS} ${CLI_LDFLAGS} %.o:%.c ${CC} ${CFLAGS} -c -o $@ $< install:${GNB_CLI} ${GNB_CRYPTO} ${GNB_ES} ${GNB_CTL} mkdir -p ./bin/ cp ${GNB_CLI} ./bin/ cp ${GNB_CTL} ./bin/ cp ${GNB_CRYPTO} ./bin/ cp ${GNB_ES} ./bin/ clean: find . -name "*.o" -exec rm -f {} \; rm -f ${GNB_CLI} ${GNB_CRYPTO} ${GNB_ES} ${GNB_CTL} rm -f core rm -f *.exe opengnb-ver1.6.0.a/Makefile.openwrt000066400000000000000000000032321500454252100172350ustar00rootroot00000000000000CFLAGS=-ffunction-sections -fdata-sections -Wno-unused-result -I./src -I./libs -I./libs/miniupnpc -I./libs/libnatpmp -I./libs/zlib -D NO_GZIP=1 -D GNB_OPENWRT_BUILD=1 CLI_LDFLAGS=-Wl,--gc-sections -L/usr/lib -pthread GNB_ES_LDFLAGS=-Wl,--gc-sections -L/usr/lib -pthread ifeq ($(DEBUG),1) CFLAGS += -g else CLI_LDFLAGS += -s GNB_ES_LDFLAGS += -s endif GNB_CRYPTO=gnb_crypto GNB_CTL=gnb_ctl GNB_ES=gnb_es GNB_CLI=gnb include Makefile.inc GNB_CLI_OBJS = \ ./src/cli/gnb.o \ ./src/gnb_argv.o \ ./src/unix/unix_platform.o \ ./src/linux/gnb_drv_linux.o GNB_ES_OBJS += ./src/unix/unix_platform.o all:${GNB_CLI} ${GNB_CRYPTO} ${GNB_ES} ${GNB_CTL} $(GNB_CTL): $(GNB_CTL_OBJS) ${CC} -o ${GNB_CTL} ${GNB_CTL_OBJS} ${CLI_LDFLAGS} $(GNB_ES): $(GNB_ES_OBJS) ${CRYPTO_OBJS} ${MINIUPNP_OBJS} ${LIBNATPMP_OBJS} ${CC} -o ${GNB_ES} ${GNB_ES_OBJS} ${CRYPTO_OBJS} ${MINIUPNP_OBJS} ${LIBNATPMP_OBJS} ${GNB_ES_LDFLAGS} $(GNB_CRYPTO): $(CRYPTO_OBJS) ./src/cli/gnb_crypto.o ${CC} -o ${GNB_CRYPTO} ./src/cli/gnb_crypto.o ${CRYPTO_OBJS} ${CLI_LDFLAGS} $(GNB_CLI): $(GNB_OBJS) $(GNB_CLI_OBJS) $(GNB_PF_OBJS) ${CRYPTO_OBJS} ${ZLIB_OBJS} ${CC} -o ${GNB_CLI} ${GNB_OBJS} ${GNB_CLI_OBJS} ${GNB_PF_OBJS} ${CRYPTO_OBJS} ${ZLIB_OBJS} ${CLI_LDFLAGS} %.o:%.c ${CC} ${CFLAGS} -c -o $@ $< install:${GNB_CLI} ${GNB_CRYPTO} ${GNB_ES} ${GNB_CTL} mkdir -p ./bin/ cp ${GNB_CLI} ./bin/ cp ${GNB_CTL} ./bin/ cp ${GNB_CRYPTO} ./bin/ cp ${GNB_ES} ./bin/ clean: find . -name "*.o" -exec rm -f {} \; rm -f ${GNB_CLI} ${GNB_CRYPTO} ${GNB_ES} ${GNB_CTL} rm -f core rm -f *.exe opengnb-ver1.6.0.a/README.md000066400000000000000000000246121500454252100153640ustar00rootroot00000000000000# OpenGNB The communication protocol of opengnb version 1.6.0 has been upgraded and is not compatible [Chinese](/README_CN.md) [English](/README.md) *Note: Most of the content of this article is translated by Google translate from the Chinese version of the "OpenGNB User Manual", the content of this article is subject to the Chinese version.* [OpenGNB](https://github.com/gnbdev/opengnb "OpenGNB") is an open source P2P decentralized Software Defined Virtual Network with extreme intranet penetration capability,Allows you to combine your company-home network into a direct-access LAN. All code related to the GNB project is released as open source, and the currently released source code supports the following platforms: FreeBSD Linux OpenWRT Raspberrypi OpenBSD macOS ## GNB Features 1. Intranet penetration P2P VPN - No public IP required 2. Extreme link capability - Unlimited speed effects 3. Data Security - Reliable authentication between GNB nodes based on elliptic curve digital signature 4. Multi-platform support - GNB is developed in C language. It does not need to refer to third-party library files when compiling. It can be easily ported to the current popular operating systems. Currently supported operating systems and platforms include Linux_x86_64, Windows10_x86_64, macOS, FreeBSD_AMD64, OpenBSD_AMD64, Raspberry Pi, OpenWRT; as big as server environment, desktop system, as small as OpenWRT router with only 32M memory can run GNB network very well. ### Standard VPN payload forwarding ```mermaid flowchart LR subgraph LAN A nodea[VPN clientA] end subgraph WAN nodef[VPN server] end subgraph LAN B nodeb[VPN clientB] end nodea <-- payload ---> nodef <-- payload ---> nodeb ``` ### GNB payload standard forwarding NAT Traversal point to point ```mermaid flowchart LR subgraph LAN A nodeA[gnb nodeA] end subgraph WAN index[gnb public index node] end subgraph LAN B nodeB[gnb nodeB] end nodeA -. nodeB address .- index -. nodeA address.- nodeB nodeA <-- payload --> nodeB ``` ### GNB payload relay forwarding ```mermaid flowchart LR subgraph LAN A nodeA[gnb nodeA] end subgraph WAN nodeC[nodeC] nodeD[nodeD] nodeE[nodeE] nodeF[nodeF] nodeJ[nodeJ] nodeK[nodeK] nodeG[nodeG] nodeH[nodeH] nodeI[nodeI] end subgraph LAN B nodeB[gnb nodeA] end nodeA[nodeA] ---- nodeC[nodeC] ---- nodeD[nodeD] ---- nodeE[nodeE] ---- nodeF[nodeF] ---- nodeB[nodeB] nodeA[nodeA] ---- nodeG[nodeG] ---- nodeH[nodeH] ---- nodeI[nodeI] ---- nodeB[nodeB] nodeA[nodeA] ---- nodeJ[nodeJ] ---- nodeK[nodeK] ---- nodeB[nodeB] ``` ### GNB payload unified forwarding ```mermaid flowchart LR subgraph LAN A nodeA[gnb nodeA] end subgraph LAN C nodeC[gnb nodeC] end subgraph LAN D nodeD[gnb nodeD] end subgraph LAN E nodeE[gnb nodee] end subgraph LAN B nodeB[gnb nodeB] end nodeA ---- nodeC & nodeD & nodeE ---- nodeB ``` ### GNB payload via tcp forwarding ```mermaid flowchart LR subgraph LAN A nodeA[gnb nodeA] upd_over_tcp_A[upd_over_tcp] end subgraph WAN upd_over_tcp_B[upd_over_tcp] nodeB[gnb nodeB] end nodeA --UDP payload--- upd_over_tcp_A --TCP payload--- upd_over_tcp_B --UDP payload--- nodeB ``` ## GNB Quick Start * Linux platform ### Step 1: Download and compile the GNB source code project ``` git clone https://github.com/gnbdev/opengnb.git cd opengnb make -f Makefile.linux install ``` After compiling, you can get `gnb` `gnb_crypto` `gnb_ctl` `gnb_es` files in the `opengnb/bin/` directory. ### Step 2: Quickly deploy GNB nodes Copy `gnb` `gnb_crypto` `gnb_ctl` `gnb_es` to host A and host B respectively. Assuming that host A and host B need to temporarily penetrate the intranet interconnection in two different LANs, the fastest way is to run gnb through lite mode. In lite mode, asymmetric encryption is not enabled, and only through **passcode** and The node id generates the encryption key, so the security will be much less modular than working with asymmetric encryption. **passcode** is a 32-bit hexadecimal string with a length of 8 characters, which can be represented as **0xFFFFFFFF** or **FFFFFFFF**, under a public index **passcode** is the same GNB node It is considered to be a node on the same virtual network. Please choose a **passcode** that will not be the same as other users as much as possible. Here, for the convenience of demonstration, the **passcode** is selected as `12345678`, and the parameter **-p ** Used to specify the **passcode** to start the node. Do not use such a simple **passcode** in actual use, it may conflict with other users who also use `12345678` as **passcode** and cause communication failure. ### Step 3: Start the first node Execute with **root** on host A ``` gnb -n 1001 -I "120.76.206.113/9001" --multi-socket=on -p 12345678 ``` After the startup is successful, execute ip addr on host A to see the GNB node IP ``` 3: gnb_do:mtu 1280 qdisc fq_codel state UNKNOWN group default qlen 500 link/none inet 10.1.0.1/16 scope global gnb_tun valid_lft forever preferred_lft forever inet6 64:ff9b::a01:1/96 scope global valid_lft forever preferred_lft forever inet6 fe80::402:c027:2cf:41f9/64 scope link stable-privacy valid_lft forever preferred_lft forever ``` ### Step 4: Start the second node Execute with **root** on host B ``` gnb -n 1002 -I "120.76.206.113/9001" --multi-socket=on -p 12345678 ``` After the startup is successful, execute ip addr on host B to see the GNB node IP ``` 3: gnb_do:mtu 1280 qdisc fq_codel state UNKNOWN group default qlen 500 link/none inet 10.1.0.2/16 scope global gnb_tun valid_lft forever preferred_lft forever inet6 64:ff9b::a01:2/96 scope global valid_lft forever preferred_lft forever inet6 fe80::a6cf:9f:e778:cf5d/64 scope link stable-privacy valid_lft forever preferred_lft forever ``` ### Step 5: Test GNB Node Interoperability At this point, if host A and host B nat penetrate successfully and ensure that there is no firewall intervention on the host, they can ping each other's virtual ip. Execute on host A ``` root @ hostA: ~ # ping 10.1.0.2 PING 10.1.0.2 (10.1.0.2) 56(84) bytes of data. 64 bytes from 10.1.0.2: icmp_seq=1 ttl=64 time=2.13 ms 64 bytes from 10.1.0.2: icmp_seq=2 ttl=64 time=2.18 ms 64 bytes from 10.1.0.2: icmp_seq=3 ttl=64 time=2.38 ms 64 bytes from 10.1.0.2: icmp_seq=4 ttl=64 time=2.31 ms 64 bytes from 10.1.0.2: icmp_seq=5 ttl=64 time=2.33 ms ``` Execute on host B ``` root @ hostA: ~ # ping 10.1.0.1 PING 10.1.0.1 (10.1.0.1) 56(84) bytes of data. 64 bytes from 10.1.0.1: icmp_seq=1 ttl=64 time=2.34 ms 64 bytes from 10.1.0.1: icmp_seq=2 ttl=64 time=1.88 ms 64 bytes from 10.1.0.1: icmp_seq=3 ttl=64 time=1.92 ms 64 bytes from 10.1.0.1: icmp_seq=4 ttl=64 time=2.61 ms 64 bytes from 10.1.0.1: icmp_seq=5 ttl=64 time=2.39 ms ``` The simplest use process of the above GNB lite mode, GNB lite mode has 5 built-in nodes, if you need more hosts to participate in the networking and use a more secure asymmetric encryption method to protect the data communication of GNB, please read the following documents carefully. ## Deep understanding of GNB guidelines The role of the index node of GNB is similar to the Tracker in the BT protocol, which is provided by some GNB network volunteers. In most cases, the `index` node only provides the address index for the hosts in the GNB network, and will not transfer data for the GNB node. The `forward` node of GNB provided by some volunteers can perform data transfer for hosts that are temporarily unable to perform point-to-point communication in extreme cases, and the asymmetric data encryption between GNB hosts makes it impossible for the `forward` node to spy on the transferred data. In extreme cases where peer-to-peer communication cannot be established, whether to transfer data through the public network `forward` node and which trusted forward node to use to transfer data depends entirely on the host owner's settings on the GNB node. In fact, even in an extremely complex network environment, GNB's superior link capability can establish virtual data links anytime, anywhere. GNB will even create multiple virtual links for hosts in the network, and choose the optimal speed path to send data packets. Here are the available `index` nodes provided by volunteers ``` i|0|101.32.178.3|9001 ``` ## Limitations of GNB 1. GNB does not support *Classless Inter-Domain Routing (CIDR)*, only supports Class A, B, C networks; 2. GNB does not forward IP frames of Default route. In `host to net` and `net to net` modes, GNB can forward data for specific subnets, but does not support full traffic forwarding; 3. The IPV6 of GNB cannot work normally under Windows platform; 4. The work of GNB using virtual network card realizes Layer 3 switching in TUN mode, and does not support Layer 2 switching if it does not support TAP mode; ### GNB related documentation * [GNB User Manual](docs/gnb_user_manual_en.md) * [Debug diagnostics for GNB](docs/gnb_diagnose_cn.md) ## GNB on OpenWRT GNB supports the OpenWRT platform and needs to be compiled by the user. ## GNB on Linux distributions The systemd script was made by [Jin Buguo](https://github.com/jinbuguo) for the GNB project The [atzlinux](https://www.atzlinux.com) project has made a deb format software package under Linux for the GNB project, and contributed it to become the official Debian software package. You may install opengnb on Debian 12 (bookworm) : ```bash apt install opengnb ``` - Arch Linux The AUR package of Arch Linux was made by [taotieren](https://github.com/taotieren) for the GNB project. The installation method is as follows ```bash # install distribution yay -Sy opengnb # Install the development version yay -Sy opengnb-git ``` For details, please visit [https://aur.archlinux.org/packages/opengnb/](https://aur.archlinux.org/packages/opengnb/) [https://aur.archlinux.org/packages/opengnb-git/](https://aur.archlinux.org/packages/opengnb-git/) [Download the compiled and released version of gnb on each platform](https://github.com/gnbdev/gnb_build "gnb_build") [gnb_udp_over_tcp](https://github.com/gnbdev/gnb_udp_over_tcp "gnb_udp_over_tcp") is a service developed for GNB that forwards UDP packets through tcp link, and can also forward data for other services based on UDP protocol. --- [Disclaimer](docs/disclaimer_cn.md) Any organization or individual is free to use GNB's source code under the GPL V3 license, this also include any commercial projects. Commercial projects that utilize GNB's source code under closed-source conditions must obtain authorization from us. opengnb-ver1.6.0.a/README_CN.md000066400000000000000000000234351500454252100157460ustar00rootroot00000000000000# OpenGNB opengnb 1.6.0 版本的通信协议已升级,不向后兼容 [Chinese](/README_CN.md) [English](/README.md) [OpenGNB](https://github.com/gnbdev/opengnb "OpenGNB") 是一个开源的 P2P 去中心化的具有极致的内网穿透能力的软件自定义虚拟网络(Software Defined Virtual Network),可以让你把公司-家庭网络组成直接访问的局域网。 ## GNB 特点 1. 极致的链路能力 - 内网穿透,无需公网IP,无限速影响,***upnp***,***multi index***,***port detect***,***multi socket*** 等策略实现内网穿透 - Discover in lan 自动发现局域网内其他节点建立 P2P 通信 - Unified Forwarding 自动通过已经建立 P2P 通信的节点转发 IP 分组,多节点重传 IP 分组 - Relay Forwarding 高度自定义中继路由,IP 分组发往下一个中继点前都会作加密处理 - Standard Forwarding 用尽一切办法无法建立起 P2P 通信的节点可以通过位于公网 forward 节点中继 IP 分组 2. 数据安全 - 基于椭圆曲线数字签名实现可靠的身份验证 - 根据时间同步变更通信密钥 - 默认选项下对日志中的敏感信息进行隐藏 3. 支持通过多核CPU加速对数据分组处理 4. 多平台支持 - GNB 用 C 语言开发,项目相关代码以开源方式发布, 编译时不需要引用第三方库文件,可以方便移植到当前流行的操作系统上,目前支持的操作系统及平台有 Linux_x86_64,Windows10_x86_64, macOS,FreeBSD_AMD64,OpenBSD_AMD64,树莓派,OpenWRT;大至服务器环境,桌面系统,小至仅有 32M 内存的OpenWRT路由器都能很好的运行 GNB 网络。 ### Standard VPN payload forwarding ```mermaid flowchart LR subgraph LAN A nodea[VPN clientA] end subgraph WAN nodef[VPN server] end subgraph LAN B nodeb[VPN clientB] end nodea <-- payload ---> nodef <-- payload ---> nodeb ``` ### GNB payload standard forwarding NAT Traversal point to point ```mermaid flowchart LR subgraph LAN A nodeA[gnb nodeA] end subgraph WAN index[gnb public index node] end subgraph LAN B nodeB[gnb nodeB] end nodeA -. nodeB address .- index -. nodeA address.- nodeB nodeA <-- payload --> nodeB ``` ### GNB payload relay forwarding ```mermaid flowchart LR subgraph LAN A nodeA[gnb nodeA] end subgraph WAN nodeC[nodeC] nodeD[nodeD] nodeE[nodeE] nodeF[nodeF] nodeJ[nodeJ] nodeK[nodeK] nodeG[nodeG] nodeH[nodeH] nodeI[nodeI] end subgraph LAN B nodeB[gnb nodeA] end nodeA[nodeA] ---- nodeC[nodeC] ---- nodeD[nodeD] ---- nodeE[nodeE] ---- nodeF[nodeF] ---- nodeB[nodeB] nodeA[nodeA] ---- nodeG[nodeG] ---- nodeH[nodeH] ---- nodeI[nodeI] ---- nodeB[nodeB] nodeA[nodeA] ---- nodeJ[nodeJ] ---- nodeK[nodeK] ---- nodeB[nodeB] ``` ### GNB payload unified forwarding ```mermaid flowchart LR subgraph LAN A nodeA[gnb nodeA] end subgraph LAN C nodeC[gnb nodeC] end subgraph LAN D nodeD[gnb nodeD] end subgraph LAN E nodeE[gnb nodeE] end subgraph LAN B nodeB[gnb nodeB] end nodeA ---- nodeC & nodeD & nodeE ---- nodeB ``` ### GNB payload via tcp forwarding ```mermaid flowchart LR subgraph LAN A nodeA[gnb nodeA] upd_over_tcp_A[upd_over_tcp] end subgraph WAN upd_over_tcp_B[upd_over_tcp] nodeB[gnb nodeB] end nodeA --UDP payload--- upd_over_tcp_A --TCP payload--- upd_over_tcp_B --UDP payload--- nodeB ``` ## GNB 快速上手 * Linux 平台 ### 步骤1: 下载编译 GNB 源码工程 ``` git clone https://github.com/gnbdev/opengnb.git cd opengnb make -f Makefile.linux install ``` 编译完毕后在 `opengnb/bin/` 目录下可以得到 `gnb` `gnb_crypto` `gnb_ctl` `gnb_es` 这几个文件。 ### 步骤2: 快捷部署 GNB 节点 把`gnb` `gnb_crypto` `gnb_ctl` `gnb_es` 分别拷贝到主机 A 和主机 B 上。 假设主机 A 和主机 B 分别在两个不同的局域网里需要临时穿透内网互联,最快捷的途径通过 lite 模式运行 gnb,在 lite 模式下没有启用非对称加密,仅通过 **passcode** 和节点 id 生成加密密钥,因此安全性会比使用非对称加密的工作模块式低很多。 **passcode** 是一个长度为8个字符的32bit的16进制字符串,可以表示为 **0xFFFFFFFF** 或 **FFFFFFFF**, 在一个 public index 下 **passcode** 相同的 GNB 节点被认为是同一个虚拟网络上的节点,请尽可能选择一个不会跟其他用户相同的 **passcode**,这里为了方便演示选定 **passcode** 为 `12345678`, 参数 **-p** 用于指定启动节点的 **passcode**。在实际使用过程中请勿使用这样简单 **passcode**,这可能会与其他同样使用`12345678`作为的 **passcode** 的用户冲突导致通信失败。 ### 步骤3: 启动第一个节点 主机 A 上用 **root** 执行 ``` gnb -n 1001 -I "120.76.206.113/9001" --multi-socket=on -p 12345678 ``` 启动成功后,主机 A 上执行 ip addr 可见 GNB 节点 IP ``` 3: gnb_tun: mtu 1280 qdisc fq_codel state UNKNOWN group default qlen 500 link/none inet 10.1.0.1/16 scope global gnb_tun valid_lft forever preferred_lft forever inet6 64:ff9b::a01:1/96 scope global valid_lft forever preferred_lft forever inet6 fe80::402:c027:2cf:41f9/64 scope link stable-privacy valid_lft forever preferred_lft forever ``` ### 步骤4: 启动第二个节点 主机 B 上用 **root** 执行 ``` gnb -n 1002 -I "120.76.206.113/9001" --multi-socket=on -p 12345678 ``` 启动成功后,主机 B 上执行 ip addr 可见 GNB 节点 IP ``` 3: gnb_tun: mtu 1280 qdisc fq_codel state UNKNOWN group default qlen 500 link/none inet 10.1.0.2/16 scope global gnb_tun valid_lft forever preferred_lft forever inet6 64:ff9b::a01:2/96 scope global valid_lft forever preferred_lft forever inet6 fe80::a6cf:9f:e778:cf5d/64 scope link stable-privacy valid_lft forever preferred_lft forever ``` ### 步骤5:测试 GNB 节点互通 此时,如果主机 A 和主机 B nat 穿透成功并确保主机上没有防火墙的干预的情况下,可以互相 ping 到对方的虚拟 ip。 主机 A 上执行 ``` root@hostA:~# ping 10.1.0.2 PING 10.1.0.2 (10.1.0.2) 56(84) bytes of data. 64 bytes from 10.1.0.2: icmp_seq=1 ttl=64 time=2.13 ms 64 bytes from 10.1.0.2: icmp_seq=2 ttl=64 time=2.18 ms 64 bytes from 10.1.0.2: icmp_seq=3 ttl=64 time=2.38 ms 64 bytes from 10.1.0.2: icmp_seq=4 ttl=64 time=2.31 ms 64 bytes from 10.1.0.2: icmp_seq=5 ttl=64 time=2.33 ms ``` 主机 B 上执行 ``` root@hostA:~# ping 10.1.0.1 PING 10.1.0.1 (10.1.0.1) 56(84) bytes of data. 64 bytes from 10.1.0.1: icmp_seq=1 ttl=64 time=2.34 ms 64 bytes from 10.1.0.1: icmp_seq=2 ttl=64 time=1.88 ms 64 bytes from 10.1.0.1: icmp_seq=3 ttl=64 time=1.92 ms 64 bytes from 10.1.0.1: icmp_seq=4 ttl=64 time=2.61 ms 64 bytes from 10.1.0.1: icmp_seq=5 ttl=64 time=2.39 ms ``` 以上是 GNB lite 模式的最简使用过程,GNB lite 模式内置5个节点,如果需要更多主机参与组网和使用更安全的非对称加密方式保护 GNB 的数据通信,请仔细阅读下面的文档。 ## 深入理解 GNB 指引 GNB 的 index 节点的角色类似于 BT 协议中的 Tracker,由一部分 GNB 网络志愿者提供。在绝大多数情况下`index`节点仅为 GNB 网内主机提供地址索引,不会为 GNB 节点中转数据。 GNB 主机之间的非对称数据加密使得 **forward** 节点无法窥探中转的数据。 在无法建立点对点通信的极端情况下,是否通过公网 **forward** 节点中转数据和使用哪个可信任的 **forward** 节点中转数据,完全取决在主机的拥有者对 GNB 节点的设置。事实上,即便处于极其复杂的网络环境,GNB 优越链路能力也可以随时随地建立虚拟数据链路,GNB 甚至会为网络中的节点创建多个虚拟链路,择速度最优路径发送数据分组。 这是由志愿者提供的可用`index`节点 ``` i|0|101.32.178.3|9001 ``` ## GNB 的限制 1. GNB 不支持 *无类别域间路由(Classless Inter-Domain Routing、CIDR)*, 仅支持 A,B,C 类网络; 2. GNB 不转发默认路由(Default route)的 IP 帧,在`host to net`和`net to net` 模式下 GNB 可以为特定的子网的数据做转发,但不支持全流量转发; 3. 在 Windows 平台下 GNB 的 IPV6 目前无法正常工作; 4. GNB 的使用虚拟网卡的工作在 TUN 模式下实现三层交换,不支持 TAP 模式即不支持二层交换; ### GNB 相关文档 * [GNB 用户手册](docs/gnb_user_manual_cn.md) * [GNB 的调试诊断](docs/gnb_diagnose_cn.md) ## GNB在OpenWRT上 GNB 支持 OpenWRT 平台,需要用户自行编译。 ## GNB 在 Linux 发行版上 [金步国](https://github.com/jinbuguo) 为 GNB 项目制作了 systemd 的脚本 [铜豌豆 Linux](https://www.atzlinux.com)项目为 GNB 项目制做了 Linux 下的 deb 格式软件包,将其贡献成为 Debian 官方软件包. 可以在 Debian 12 (bookworm) 下直接安装: ```bash apt install opengnb ``` - Arch Linux [taotieren](https://github.com/taotieren) 为 GNB 项目制作了 Arch Linux 的 AUR 包 详情请访问 [https://aur.archlinux.org/packages/opengnb/](https://aur.archlinux.org/packages/opengnb/) [https://aur.archlinux.org/packages/opengnb-git/](https://aur.archlinux.org/packages/opengnb-git/) ### 相关链接 [wuqiong](https://www.github.com/wuqiong) 为 GNB 在Windows平台上开发了 wintun 虚拟网卡的接口模块 [gnb 在各平台的编译发行版下载](https://github.com/gnbdev/gnb_build "gnb_build") [gnb_udp_over_tcp](https://github.com/gnbdev/gnb_udp_over_tcp "gnb_udp_over_tcp") 是一个为 GNB 开发的通过 tcp 链路中转 UDP 分组转发的服务,也可以为其他基于 UDP 协议的服务中转数据。 --- [免责声明](docs/disclaimer_cn.md) 个人和商业可以在遵循gplv3许可下免费自由使用gnb的源码,如果想闭源使用opengnb的源码,需取得开发团队的商业授权. opengnb-ver1.6.0.a/docs/000077500000000000000000000000001500454252100150305ustar00rootroot00000000000000opengnb-ver1.6.0.a/docs/disclaimer_cn.md000066400000000000000000000017431500454252100201530ustar00rootroot00000000000000# 免责声明 [OpenGNB](https://github.com/gnbdev/opengnb "OpenGNB")是一个开源的去中心化的具有极致内网穿透能力的通过 P2P 进行三层网络交换的虚拟组网系统。 [gnb_udp_over_tcp](https://gitee.com/gnbdev/gnb_udp_over_tcp "gnb_udp_over_tcp")是一个为 GNB 开发的通过 tcp 链路中转 UDP 分组转发的服务,也可以为其他基于 UDP 协议的服务中转数据。 用户使用本项目的软件及相关项目源码、脚本、配置文件即表示用户并同意以下免责条款。 在一个计算机及计算机所在网络中部署运行 GNB 及衍生项目的软件会涉及该计算机及所在网络的安全,请用户在部署运行 GNB 及衍生项目的软件之前务必确认用户的计算机及所在的计算机网络的管理者是否允许用户这样做,并且要严格遵循用户所在地的法律法规。 GNB 开发组织不对用户部署运行 GNB 及衍生项目的软件的行为造成的任何后果负责。 opengnb-ver1.6.0.a/docs/gnb_diagnose_cn.md000066400000000000000000000054131500454252100204540ustar00rootroot00000000000000[OpenGNB](https://github.com/gnbdev/opengnb "OpenGNB")是一个开源的去中心化的具有极致内网穿透能力的通过P2P进行三层网络交换的虚拟组网系统。 一些运行GNB的节点处于的网络可能非常复杂,虽然GNB尽最大可能让这些节点通过NAT穿透互连,但是总是难以避免会遇到一些节点在NAT时会失败,这在P2P通讯中是不可避免的。 造成一些节点无法互连的原因还可能有: 节点之间由于没有正确的交换公钥,如果节点采用时钟同步更新密钥但一些节点的时钟没有和其他节点的时钟同步也会导致互连失败。 为了诊断当前GNB与其他节点互连的情况,提供了一个叫`gnb_ctl`的工具来查看当前GNB进程内部的状态。 在介绍`gnb_ctl`之前,要先介绍一下gnb内部的一个机制,gnb在设计之初就考虑到如何将gnb进程内部大部分的核心的状态暴露出来,这样用户不需要通过观察gnb的日志就能了解到gnb进程的工作状况,例如当前节点与哪些节点是成功建立了连接,也可以根据这些信息判断某些节点没有互连成功的原因。 这个机制就是共享内存,gnb内部几乎所有的重要的数据结构所使用的内存都不是从堆上获得,而是通过mmap一块内存与 `gnb_ctl` `gnb_es` 共享,通常情况是gnb进行负责更新这块共享内存,`gnb_ctl` `gnb_es` 多数时候是读取这块内存。 如果启动gnb时不通过参数指定,这块mmap内存对应的文件 gnb.map 将在节点配置目录中创建。 Unix系的mmap系统调用几乎都是一样,除了个别平台特性相关的参数,唯独Windows创建共享内存的API是独有的,因此gnb特地对Unix系和Windows的共享内存做了一个封装,具体代码在 `gnb_mmap.h gnb_mmap.c`,现在这部分代码已经公开。 由于启动 gnb 通常是root用户,因此通过`gnb_ctl`打开这块共享内存也需要用root用户。 当gnb启动后,执行下面的命令就能看到gnb内部的状态, `./gnb_ctl -b ../../conf/1001/gnb.map -c` 输出的信息中会列出所有节点的连通状态,如果一个节点的信息中有 `ipv6 REACHABL` 或在 `ipv4 REACHABL` 就说明这个节点与当前节点当然成功连通的。 用户可以通过这些信息排查节点无法连通的原因,其中包括当前节点与其他节点通讯时使用的密钥,这些信息涉及到通讯的安全不应当透露给无关的他人。 当确实遇到无法连通的节点,这样可能就需要通过`forward`节点去为这些节点提供数据中转服务,这样这些节点就从点对点网络转变为中心化网络。 如名字的含义,`gnb_ctl`将来还可以做更多的事情。 需要了解更多细节可以执行`gnb_ctl -h` 了解。 opengnb-ver1.6.0.a/docs/gnb_user_manual_cn.md000066400000000000000000001215151500454252100212000ustar00rootroot00000000000000OpenGNB 用户手册 version 1.3.0.0 protocol version 1.2.0 # 概述 [OpenGNB](https://github.com/gnbdev/opengnb "OpenGNB") 是一个开源的 P2P 去中心化的具有极致的内网穿透能力的软件自定义虚拟网络(SDVN)。 GNB 是一个去中心化的网络,网络中每个节点都是对等的,没有 Server 和 Client 的概念。 在一个 GNB 网络中每个节点的 ID 是唯一的,被称为 **nodeid** ,这是一个 32bit 无符号整型数字。 GNB 节点可以通过 index 节点找到其他 GNB 节点并建立起通信,在这过程中 GNB index 节点的作用类似于 **DNS** 和 **Bit Torrent** 中的 **tracker** 。 GNB 与 index 节点通信时使用 **ed25519** 的 public key 和 `passcode` 与 **nodeid** 的 sha512 摘要作为唯一标识,基于这个特点,一个 GNB index 节点可以为许多个 GNB 网络 提供 index service 而不容易发生碰撞冲突。 GNB 节点也可以通过域名或静态 IP 地址或内网广播找到其他 GNB 节点。 GNB 通过***upnp***,***multi index***,***port detect***,***multi socket***, ***unified forwarding*** 等许多办法使得位于 LAN 中的节点能够成功 NAT 穿透与其他节点建立 P2P 通信,最糟糕的情况下,当两个 GNB 节点无法建立起P2P连接时可以通过网络内其他节点中转 payload。 GNB目前支持的操作系统及平台有 Linux,Windows10, macOS,FreeBSD,OpenBSD,树莓派,OpenWRT,除有特别的说明,本文档适用于这些支持的平台发行版及针对特定平台源码编译的版本。 # 部署 GNB ## GNB Public Index node **GNB Public Index node** 仅提供 index service,不打开 TUN 设备,不创建虚拟IP,不处理 IP 分组,不需要用 root 启动,由志愿者提供。 以 **Public Index** 方式启动 GNB 节点 启动默认监听 9001 端口 ``` gnb -P ``` 启动监听 9002 端口 ``` gnb -P -l 9002 ``` ## GNB 的 Lite Mode 在 **Lite Mode** 下不需要为节点创建 **ed25519** 密钥对 和 配置文件,通过设定命令行参数就能启动 GNB 节点。 在 **Lite Mode** 下 **upnp** 选项默认被启用。 GNB的源码 里 hardcode 了一个有5个节点的 GNB 网络供 **Lite Mode** 下使用,这极大了简化部署的过程。 ``` nodeid tun address 1001 10.1.0.1/255.255.0.0 1002 10.1.0.2/255.255.0.0 1003 10.1.0.3/255.255.0.0 1004 10.1.0.4/255.255.0.0 1005 10.1.0.5/255.255.0.0 ``` **Lite Mode** 下的 GNB 节点 通过 `passcode` 生成通讯密钥,安全性远低于基于 **ed25519** 的非对称加密的安全模式。 **Lite Mode** 下的 GNB 节点与 index 节点通信时使用 `passcode` 与 **nodeid** 的 sha512 摘要作为唯一标识,假设两个 **Lite Mode** 下的 GNB 网络使用了相同 `passcode` 和 index 节点,毫无疑问这必然互相干扰。 以下是一组命令,分别运行在 主机 A 和 主机 B上实现虚拟组网,需要用 **root** 执行 主机 A 上 ``` gnb -n 1001 -I "$public_index_ip/$port" -l 9001 --multi-socket=on -p 12345678 ``` 主机 B 上 ``` gnb -n 1002 -I "$public_index_ip/$port" -l 9002 --multi-socket=on -p 12345678 ``` 此时应可以看到主机 A 上的 TUN IP 是 10.1.0.1, 主机 B 上的 TUN IP 是 10.1.0.2,此时,两个节点如果建立起连接 P2P 通讯就可以互相访问。 用户当然可以在 **Lite Mode** 下设置更多的节点,这需要了解 `gnb` 的 `-n`, `-I`, `-a,`, `-r`,`-p` 等参数的使用。 ## GNB 的 Safe Mode 以 **Safe Mode** 方式启动 GNB 需要正确设置 `node.conf` `address.conf` `route.conf` 文件以及 **ed25519** 公私钥,这些文件需要放在一个目录下,目录的名字可以是 **nodeid**。 其中,`address.conf` 是可选的。 假设一个nodeid为`1000`的节点固定运行在 WAN 上充当 index 节点的角色,其他GNB节点通过 `address.conf` 的配置找到 `1000`节点,如此场景下`1000`节点一般不需要`address.conf` 。 如果创建了多个 GNB 节点,可以把这些节点的配置目录放在 `gnb/conf/` 下以便管理。 ## 目录结构 以节点 `1001` `1002` `1003`为例, 这些节点的配置目录如下 ``` gnb/conf/1001/ gnb/conf/1001/node.conf gnb/conf/1001/address.conf gnb/conf/1001/route.conf gnb/conf/1001/security/1001.private gnb/conf/1001/security/1001.public gnb/conf/1001/ed25519/1002.public gnb/conf/1001/ed25519/1003.public gnb/conf/1001/scripts ``` ``` gnb/conf/1002/ gnb/conf/1002/node.conf gnb/conf/1002/address.conf gnb/conf/1002/route.conf gnb/conf/1002/security/1002.private gnb/conf/1002/security/1002.public gnb/conf/1002/ed25519/1001.public gnb/conf/1002/ed25519/1003.public gnb/conf/1002/scripts ``` ``` gnb/conf/1003/ gnb/conf/1003/node.conf gnb/conf/1003/address.conf gnb/conf/1003/route.conf gnb/conf/1003/security/1003.private gnb/conf/1003/security/1003.public gnb/conf/1003/ed25519/1001.public gnb/conf/1003/ed25519/1002.public gnb/conf/1003/scripts ``` 假设这些节点的配置目录已经分别部署到不同的主机上,启动`1001` `1002` `1003` 节点的命令可以是: ``` gnb -c gnb/conf/1001 gnb -c gnb/conf/1002 gnb -c gnb/conf/1003 ``` `scripts/`目录下存放的是在虚拟网卡启动/关闭后调用的脚本,用于用户自定义设置路由,防火墙的指令。 `security/` 存放的是本节点的 **ed25519** 公钥和私钥,`ed25519/` 存放的是其他节点的公钥。 ## 密钥交换 **Safe Mode** 下,GNB 节点通过非对称加密(ed25519)来交换通讯密钥,这是 GNB 节点通信的基础,因此需要为每个 GNB 节点创建一组公私钥用于通讯。 公私钥的命名分别是以节点的UUID为文件名 .private 和 .public 为文件的后缀名,以 UUID 为 1001 的节点公私钥文件应为 `1001.public` `1001.private` GNB 提供了一个名为 `gnb_crypto` 命令行工具,用于生成公私钥, 为 `1001` `1002` `1003` 节点 创建 **ed25519** 公私钥的命令是: `gnb_crypto -c -p 1001.private -k 1001.public` `gnb_crypto -c -p 1002.private -k 1002.public` `gnb_crypto -c -p 1003.private -k 1003.public` 交换公钥,就是要把这些 **ed25519** 公私钥 放置到正确的目录中。 在 **nodeid** 为 `1001`的节点上: `gnb/conf/1001/security/` 目录下应该有 `1001.private` `1001.public` `gnb/conf/1001/ed25519/` 目录下应该有 `1002.public` `1003.public` 在 nodeid 为 `1002`的节点上: `gnb/conf/1002/security/` 目录下应该有 `1002.private` `1002.public` `gnb/conf/1002/ed25519/` 目录下应该有 `1001.public` `1003.public` 在 nodeid 为 `1003`的节点上: `gnb/conf/1003/security/` 目录下应该有 `1003.private` `1003.public` `gnb/conf/1003/ed25519/` 目录下应该有 `1001.public` `1002.public` 在非对称加密基础上同一个 GNB 网络下的节点还可以通过设置相同 `passcode` 以保护通讯密钥。 GNB通讯密钥有关的信息需要参考 `--crypto` `--crypto-key-update-interval` `--passcode` 的说明。 ## GNB payload forwarding - **Direct Forwarding** 节点间 P2P 通信;通常情况下,位于 WAN 上节点必可与其他节点建立起 P2P 通信,位于 LAN 中节点与其他 LAN 中的节点建立起 P2P 通信要经过NAT穿透; - **Unified Forwarding** 自动通过已经建立 P2P 通信的节点转发 IP 分组,多节点重传 IP 分组; - **Relay Forwarding** 高度自定义中继路由,IP 分组发往下一个中继点前都会作加密处理,相关设置在 `route.conf`; - **Standard Forwarding** 用尽一切策略都无法建立起 P2P 通信的节点可以通过位于公网 forward 节点中继 IP 分组 ## node.conf 配置文件 以下是 `node.conf` 一个例子: ``` nodeid 1001 listen 9001 ``` `node.conf` 用于存放节点的配置信息,格式如下 ``` nodeid $nodeid listen $listen_port ``` 或 ``` nodeid $nodeid listen ip_address:$listen_port ``` GNB 支持IPV6和IPV4。 有一些值得重点关注的选项,可以很好提升 GNB 的 NAT 穿透能力: ``` es-argv "--upnp" ``` 尝试打开 upnp ,让来自 WAN 的 IP 分组更容易被传入。 ``` multi-socket on ``` 打开更多 UDP 监听端口,增加NAT穿透端口探测成功的概率。 `multi-socket` 被设为 on 后会除原有的 `listen` 的端口外,在额外打开4个随机 UDP 端口,如果想额外监听指定的端口,可以用多个 `listen` 设置项,GNB 支持用`listen` 指定监听5个地址端口或通过`listen6` 监听 5个IPV6地址和端口 以及用 `listen4` 监听5个IPV4地址端口。 ``` unified-forwarding super ``` 在发送 ip 分组的过程通过多个已经分别和A,B节点都建立起 P2P 通信的节点对 TCP 类型的 ip 分组进行重传中转 `node.conf` 所支持的配置项与 gnb 命令行参数一一对应,目前支持的配置项有: ``` ifname nodeid listen listen6 listen4 ctl-block multi-socket direct-forwarding unified-forwarding ipv4-only ipv6-only passcode quiet daemon mtu set-tun address-secure node-worker index-worker index-service-worker node-detect-worker port-detect-range port-detect-start port-detect-end pid-file node-cache-file log-file-path log-udp4 log-udp-type console-log-level file-log-level udp-log-level core-log-level pf-log-level main-log-level node-log-level index-log-level detect-log-level es-argv ``` ### route.conf 配置文件 GNB 节点之间通信的数据分组被称为 **gnb payload**,网络里所有的节点共享的一张路由表,配置文件是 `route.conf`,其作用就是告诉 GNB 核心如何"route" 这些包含 IP 分组的 **gnb payload**。 每个路由配置项占一行,路由配置项有两个类型 **forward** 与 **relay** 用于设定本地节点的 payload 到达对端节点的方式。 以下是 `route.conf` 的例子: ``` 1001|10.1.0.1|255.255.255.0 1002|10.1.0.2|255.255.255.0 1003|10.1.0.3|255.255.255.0 ``` 配置文件中的每一行是一个节点的描述,格式如下 ``` $nodeid|$tun_ipv4|$tun_netmask ``` 每个配置项的含义是这样: `$nodeid` 节点的UUID `$tun_ipv4` 虚拟网卡的IPV4地址 `$tun_netmask` 虚拟网卡的IPV4地址的子网掩码 #### Direct forwarding 节点之间通信默认是点对点方式被称为**Direct forwarding**,即 IP 分组直接发往对端节点的IP地址和端口。 例如 `route.conf` 中 有一行 ``` 1001|10.1.0.1|255.255.255.0 ``` 当 GNB 处理一个目的地址 是 10.1.0.1 的 IP 分组时,就确定这个 IP 分组需要用 **nodeid** 为 1001 的节点的通信密钥加密封装成 **gnb payload** 发送到该节点 1001 上,这个过程我们称为 **Direct forwarding**。 #### Standard Forwarding 节点之间在没有起建立P2P通讯的情况下可以通过 `address.conf` 中有定义了 **f** 属性的 **forward** 节点转发**gnb payload**,这个通讯方式被成为 **Standard Forwarding** 例: `address.conf` ``` if|1001|x.x.x.x|9001 ``` 以上例子中 1001 节点是一个 **idnex** 节点,同时也是一个 **forward** 节点。 #### Relay Forwarding **Relay Forwarding** 通过明确的自定义的中继路径对 **gnb payload** 进行中继,**gnb payload** 在中继过程中会被中继节点再次加密。 由于是端对端加密,**forward node** 与 **relay node** 节点无法得到通信的两端的 **gnb payload** 中的 IP 分组的明文。 为目的节点设定中继节点, 可以为一个对端的节点设置最多8条中继的路由,每条中继路由最多可以有5个中继节点。 以下是 `route.conf` type relay 一些例子: ``` 1006|1003 1006|auto,static ``` 这组 route 的作用是:在当前节点无法与 1006 节点建立起 P2P 通信时,将通过 1003节点中继发往 1006 节点的 IP 分组。 ``` 1006|1003,1004,1005 1006|force,static ``` 这组 route 的含义是:当前节点发往 1006 节点 的 IP 分组强制按顺序通过 1005,1004,1003 中继到 1006 节点。 ``` 1006|1003,1005 1006|1005,1004 1006|1005,1003 1006|force,balance ``` 这组 route 的作用是:当前节点到1006节点有3条中继路由,发送 IP 分组时选择路由的策略是负载均衡。 相关的设置项格式如下: ``` $nodeid|$relay_nodeid3,$relay_nodeid2,$relay_nodeid1 $nodeid|$relay_mode ``` 本地节点的payload通过中继节点到达对端节点的路径是 local_node => relay_node1 => relay_node2 => relay_node3 => dst_node, 而 dst_node 到 local_node 的路径则由对端的 dst_node 的 `route.conf` 配置所决定。 `$relay_mode` 可以是 **auto**, **force**, **static**, **balance** **auto** 当对目的节点无法点对点通信及没有forward节点转发时通过预设的中继路由转发 **force** 强制与该目的节点的通信必须经过中继路由 **static** 当一个目的节点有多条中继路由时,使用第一条中继路由 **balance** 当一个目的节点有多条中继路由时,以负载均衡的方式选择中继路由 ### address.conf 配置文件 `address.conf` 用于配置节点的属性和公网ip地址及端口,以下是一个例子: ``` i|0|a.a.a.a|9001 if|1001|b.b.b.b|9001 n|1002|c.c.c.c|9001 ``` 文件中的 `a.a.a.a` `b.b.b.b` `c.c.c.c` 代表节点的物理网卡的 IP 地址,需要根据实际情况填写,配置文件中的每一行是一个地址的描述,格式如下: ``` $attrib|$nodeid|$ipv4/$ipv6/$hostname|$port ``` `$attrib` 节点的属性,用一组字符来表示,**i**表示这个节点是index节点; **f**表示这个节点是forward节点; **n** 表示这个节点是一个普通节点; **s**为静默(slience)节点,本地节点如果含有**s**属性将不会与index节点通信避免,也不会响应ping-pong及地址探测的请求暴露本地ip地址 `$nodeid` 节点的 nodeid,与 `route.conf` 中的 `$nodeid` 相对应 `$ipv6` GNB 节点的 IPV6 地址 `$ipv4` GNB 节点的 IPV4 地址 `$hostname` GNB 节点的 域名 `$port` GNB 节点的服务端口 如果一个节点拥有多个 IP 地址, 需按格式分成多行配置,GNB 会通过 **GNB node ping-pong** 协议方式去测量该节点每个 IP 地址的时延,在发送 IP 分组数据的时候自动发往低时延的IP地址。 `gnb` 进程不会对 `address.conf` 中的 `$hostname` 进行域名解释,而是由 `gnb_es` 异步处理,相关信息可以了解 `gnb_es` 的 `--resolv` 选项。 前文提到 index 节点的作用类似于 **DNS** 和 **Bit Torrent** 中的 **tracker**, 如果一组相互之间不知道对方 IP 地址和端口的 GNB 节点都向同一个 index 节点提交自身的 IP 地址和端口, GNB 节点就可以通过对端节点的公钥向 index 查询对端节点的 IP 地址和端口。 在 `address.conf` 中 index 节点的 `$attrib` 里需要带有 **i** 属性。 GNB index 协议允许在提交和查询节点ip地址端口过程中不验证报文的数字签名,即 index 节点允许对提交和查询ip的报文不验证数字签名,节点对 index 节点响应查询IP的报文不验证数字签名。 **GNB Public Index node** 在 `address.conf` 中的对应的 **nodeid** 可以设为 **0**,不需要在 `route.conf` 中设定 "route" 规则,以下是一个 **GNB Public Index node** 的例子: ``` i|0|a.a.a.a|9001 ``` forward 节点 `$attrib` 设为 **f**, `$nodeid` 不能设为 **0**,并且必须绑定 nodeid 作为配置项出现在 `route.conf` 中, gnb forward 协议相关的报文都要发送验证节点的数字签名,即要求 forward 节点和通过 forward 节点转发报文的节点都必须相互交换了公钥。 forward 节点可以为无法直接互访的 GNB 节点中转 IP 分组,这些节点通常部署在内网中且没有固定公网 IP,并且用尽了所有的办法都无法实现nat穿透实现点对点通讯,forward 节点并不能解密两个节点之间的通信的内容。 用户当然可以把一个 GNB 节点作为GNB网络中的 index节点 和 forward节点,同时还可以为其他 GNB 网络提供 index service,以下是一个例子: ``` if|1001|b.b.b.b|9001 ``` 在 `address.conf` 中 index 节点和 forward 节点可以有多项,并可以通过 `--multi-index-type` `--multi-forward-type` 设定负载均衡和容错的模式;假设一个 GNB 节点在LAN中经过非常复杂的地址转换后可能在同一时刻拥多个NAT后的 IP 地址,即运营商可能会根据 LAN 中的主机访问 WAN 的目标地址选用不同的网关出口,这时如果 `address.conf` 设有多个 Index 节点,那么在 NAT 穿透中,对端的GNB节点就可能掌握到该节点更多的地址与端口,从而增加NAT穿透建立 P2P 通信的成功率。 ## GNB Unified Forwarding 在复杂 NAT 机制下,位于 LAN 中的节点无法确保可以 100% 成功实现 NAT 穿透,但总会有一些节点可以成功实现 NAT 穿透建立起 P2P 通讯,**GNB Unified Forwarding** 机制可以使得已经建立起 P2P 通讯的节点为未建立起 P2P 通讯的节点转发 IP 分组。 GNB 网络中每个节点定期把与自身建立起 P2P 通讯的节点id在网内通告,这使得网内每个节点都掌握发送数据另一个节点时有哪些中转节点可用。 以一个有A、B、C 3个节点的GNB网络为例: A与C, B与C 都建立起 P2P 通讯,而 A 与 B 由于复杂的 NAT 机制无法建立起 P2P 通讯,通过 **GNB Unified Forwarding** 机制,A与B 可以通过 C 转发 IP 分组。 根据 **GNB Unified Forwarding** 的机制只要虚拟网络中节点的数量越多,节点之间越容易实现 NAT 穿透并建立起虚拟链路。 发往目标节点的 IP 分组可以同时由多个中转节点转发,先到达目标节点的 IP 分组会被写入虚拟网卡,GNB 对每个目标节点维护了一个 64bit 时间戳及时间戳队列以确保重复传输的 IP 分组 被丢弃,因此**GNB Unified Forwarding**这个特点在一些场合下可以用作TCP重传加速。 ### GNB Unified Forwarding 工作模式 `auto` 当A、B两个节点无法建立 P2P 通信时,自动通过已经分别和A,B都建立起 P2P 通信的节点(可以在LAN中)进行中转 IP 分组 `super` 不管A、B两个节点有没有建立起 P2P 通信,在发送 ip 分组的过程通过多个已经分别和A,B都建立起 P2P 通信的节点对 TCP 类型的 ip 分组进行重传中转 `hyper` 不管A、B两个节点有没有建立起 P2P 通信,在发送 ip 分组的过程通过多个已经分别和A,B都建立起 P2P 通信的节点对所有类型的 ip 分组进行重传中转 要了解更多 **Unified Forwarding** 的信息,可以参考 `gnb` 的 `-U, --unified-forwarding` 选项 ## GNB Discover In Lan **Discover In Lan** 可以使得 GNB 节点通过广播发现 LAN 内其他的 GNB 节点,这使得同一个 LAN 下的 GNB 节点就不需要先经过 WAN 进行 NAT 穿透就能建立起通信。 **Discover In Lan** 在 `gnb_es` 中实现,为了让 `gnb_es` 进程可以一直监听 LAN 中其他节点的广播分组,`gnb_es` 必须以 service 或 daemon 方式启动,并带有 `-L, --discover-in-lan` 选项。 以下节点 1002 为例 ``` gnb_es -s -L -b gnb/conf/1002/gnb.map ``` `gnb.map` 是 `gnb` 进程创建的共享内存映射文件,如果没有特别指定,这个映射文件会在节点的配置目录中(`gnb/conf/1002/`)被创建;通过这块共享内存,`gnb_es` 可以把 LAN 中监听到的来自其他 GNB 节点的信息传递给 gnb 进程;与此同时,`gnb_es` 还会定期在 LAN 中广播自身节点的信息使得可以被 LAN 中其他节点发现。 在部署 GNB 节点的过程中,用户会发现在某些情况下同一个 LAN 里某些 GNB 节点可以成功NAT 穿透与另一个异地的 LAN 里的节点成功建立 P2P 通信,而某些节点却未能成功,借助 **Discover In Lan** 不但可以让更多的节点更轻易的连结在一起,同时还可以使得让已经成功NAT 穿透的节点去帮助同一个 LAN 下其他节点转发 IP 分组。 要了解更多 **Discover In Lan** 的信息,可以参考 `gnb` 的 `-b, --ctl-block`,以及 `gnb_es` 的 `-s, --service` `-d, --daemon` `-L, --discover-in-lan` 选项。 ## 用 zip 压缩数据分组 `--zip` auto 当数据压缩后比原始数据大将发送原始数据 force 当数据压缩后比原始数据大将发送压缩后的数据 `--zip-level` 0 不压缩 1~9 压缩率 1 最低压缩率, 9是最高压缩率 node.conf 支持该选项 ## 利用多核CPU加速数据分组处理 `--pf-worker` 默认是0,即使用单个线程处理ip数据分组 最大不超过128个线程 node.conf 支持该选项 ## 内存规模 `--memory` 可选项有 tiny,small,large,huge,默认是:"tiny" node.conf 支持该选项 ## 关于 net to net 一般而言,VPN通过建立虚拟链路的方式可以把几台计算机组成一个网络,也可以让一台计算机通过虚拟链路接入一个网络,还可以通过虚拟链路把两个或者更多的计算机网络组成一个大的虚拟网络,使得分散在各自不同网络里的计算机可以互相访问。 这种通过VPN的虚拟链路把几个网络整合成一个虚拟网络的架构我们称为 ** net to net **。 GNB 让 ** net to net ** 的部署变得非常轻而易举,借助 GNB 强大的 NAT 穿透能力,GNB可以轻易的把几个分别位于不同地方的 LAN 组成一个虚拟网络,并且大多数时候这些 LAN 之间是 P2P 直接通信而不需要中心节点中转,这样网络之间的通信就不受限于中心节点的带宽。 假设有两个异地的 **LAN A** 和 **LAN B** 通过 NAT 访问互联网,这两个 LAN 的网关都是 OpenWRT Router,那么只需要在 OpenWRT Router 上部署两个 GNB 节点,借助 WAN 上 GNB index 节点 实现 NAT 穿透, **LAN A** 和 **LAN B** 里的主机就能互相访问。 假设有两个异地的 **LAN A** 和 **LAN B** 通过 NAT 访问互联网,这两个 LAN 的网关都是 OpenWRT Router,那么只需要在 OpenWRT Router 上部署两个 GNB 节点通过 NAT 穿透建立起 P2P 通信, **LAN A** 和 **LAN B** 里的主机就能互相访问。 在这个过程中,通常需要有位于 WAN 上 GNB index 节点帮助这两个 GNB 节点找到对方,在以下的例子中,为了确保这两个节点在 NAT 穿透不成功的情况下还能通信,可以部署一个 forward 节点同时兼提供 index service。 这样,就总共有3个 GNB 节点需要部署: **nodeid**=1001 位于 WAN,作为 index 和 forward 节点,IP= x.x.x.x port = 9001 **nodeid**=1002 位于 **LAN A** 的 OpenWRT Router 上,NetWork=192.168.0.0/24 **nodeid**=1003 位于 **LAN B** 的 OpenWRT Router 上,NetWork=192.168.1.0/24 设置 **node 1001** `conf/1001/node.conf` ``` nodeid 1001 listen 9001 ``` `conf/1001/route.conf` ``` 1001|10.1.0.1|255.255.255.0 1002|10.1.0.2|255.255.255.0 1003|10.1.0.3|255.255.255.0 ``` 设置 **LAN A** 中的 **node 1002** `conf/1002/node.conf` ``` nodeid 1002 listen 9002 multi-socket on es-argv --upnp ``` `conf/1002/route.conf` ``` 1001|10.1.0.1|255.255.255.0 1002|10.1.0.2|255.255.255.0 1003|10.1.0.3|255.255.255.0 1003|192.168.1.0|255.255.255.0 ``` `conf/1002/address.conf` ``` if|1001|x.x.x.x|9001 ``` **x.x.x.x** 是 node 1001 的 WAN IP,需要根据实际情况填写。 `conf/1002/scripts/if_up_linux.sh` ``` ip route add 192.168.1.0/24 via 10.1.0.3 ``` 这个路由指令的作用是:当 **LAN A** 里的主机要发送目标地址是 `192.168.1.0/24` 的IP分组时,由于 **LAN A** 的网络是 `192.168.0.0/24`,所以这些目的是`192.168.1.0/24` IP 分组将会发送默认网关 OpenWRT Router 上,由于设置了这条路由规则,这些 IP 分组会被转发到 TUN 设备上被 GNB 进程获取封装成 **gnb payload**最终发送到 **node 1003** 上。 毫无疑问,在 **node 1003** 上也需要有类似的路由指令使得目的地是 `192.168.0.0/24` 的 IP 分组能够到达 **node 1003** GNB 进程最终被发送到 **node 1002**上。 设置 **LAN B** 中的 **node 1003** `conf/1003/node.conf` ``` nodeid 1003 listen 9003 multi-socket on es-argv --upnp ``` `conf/1003/route.conf` ``` 1001|10.1.0.1|255.255.255.0 1002|10.1.0.2|255.255.255.0 1003|10.1.0.3|255.255.255.0 1002|192.168.0.0|255.255.255.0 ``` `conf/1003/address.conf` ``` if|1001|x.x.x.x|9001 ``` `conf/1003/scripts/if_up_linux.sh` ``` ip route add 192.168.0.0/24 via 10.1.0.2 ``` 通常情况下, OpenWRT 默认设有一些防火墙规则,这可能会导致 GNB 转发到当前 LAN 中的主机的 IP 分组被拦截,所以,这里还需要检测 OpenWRT,一般的要 把防火墙中的 Forward 选项 设置 为 accept,还有就是与 Wan 有关的 Forwardings 设置为 accept 。 确认配置正确后,可以先启动 **node 1001**,然后是 **node 1002** 和 **node 1003**,这样 **node 1001** 就能第一时间为 **node 1002** 和 **node 1003** 提供 index service 。 把 **node 1001**,**node 1002** ,**node 1003** 都启动后,可以先尝试这3个 GNB 节点对应的虚拟IP,即 `10.1.0.1` `10.1.0.2` `10.1.0.3` 能否成功通过 ping 测试。 如果一切顺利的话,就可以尝试从 **LAN A** 中某台主机去 ping **LAN B** 下某台主机 。 例如从位于 **LAN A** 下 IP 为 `192.168.0.2` 的主机上去 ping 位于 **LAN B** 下的 IP 为 `192.168.1.2` 的主机,毫无疑问,也可以反方向来测试。 到这一步,如果发现这3个 GNB 节点对应的虚拟IP可以通过 ping 测试,而两个 LAN 里面的主机无法通过 ping 测试,那么可以回到前面的步骤检查 OpenWRT 上的防火墙规则还有检测主机上的防火墙规则。 # GNB 的 NAT 穿透 极致的 NAT 穿透能力或许是 GNB 最令人激动的一个特性,但绝这不是 GNB 的全部,GNB 还有许多有价值的特性待用户去挖掘。 在复杂的网络环境下, 成功 NAT 穿透与其他节点建立 P2P 通信有时并不容易,为了提升节点的 NAT 穿透成功的概率有必要较详细的介绍 NAT (Network Address Translation) 和 GNB 在 NAT 穿透方面做的工作。 通常,对于一些在 LAN 里通过 NAT 访问互联网的主机,在 NAT (Network Address Translation) 的过程中会涉及到包括但不限于诸如 LAN 中的路由设备, 网络结构,运营商所使用的网络设备,网络架构,NAT策略等许多几乎是“黑盒"般的网络环境,一个分组的IP地址可能经过多次转换,可能有多个出口网关,这些都是 NAT 穿透过程中的不确定因素。 **Don't talk about the white paper, who known? who care?** **Don't talk about the type of NAT, I don‘t f*cking care** **What GNB has to do, just try it's best to traverse the NAT** 毫无疑问,GNB 从 **Bit Torrent** 这些 P2P 软件中获得灵感,既然两个位于不同的 LAN 中的主机通过 NAT 访问互联网能够建立起 P2P 通信用于传输文件的数据块,那么就意味这样的方式也能用于传输虚拟网卡的 IP 分组。 GNB 用尽各种策略去促使每个节点能够 NAT 穿透的成功,这些策略中,一些策略非常有效,一些效果不大,一些策略在某些场合效果不错而在另一些场合就可能没有效果。 首先,本地节点通过与 index 节点通信交换信息获得其他节点的 WAN 地址和端口并尝试和这些节点进行联系; 事实上,一些节点的在经过 NAT 之后会用一个以上的 WAN 地址去访问互联网,GNB 支持同时与多个 index 节点交换信息,这样就有机会发现对端节点更多的 WAN 地址。 对于`route.conf`中定义的且未建立起 P2P 通信的对端节点,GNB 进程会定期向 index 节点查询这些节点的 WAN 地址端口,并尝试发起通信。 GNB 会对以及获得 WAN 地址但未建立起 P2P 通信的对端节点发现小范围的端口探测,如果两个节点相互能收到对端的探测请求 P2P 通信就基本打通。 GNB 还有专门的线程对未能建立起 P2P通信的接单定期进行大范围的端口探测。 与 **Bit Torrent** 等多数的 P2P 软件一样,GNB 也会通过 UPNP 在出口网关上尝试建立地址端口映射以提升 NAT 穿透成功率。 需要注意的是,如果一个 LAN 有多个主机部署 GNB 节点并开启 UPNP,这些节点不应监听相同的端口,这会导致在网关建立 UPNP 端口映射时发生冲突。 主机所在的网关如果支持和启用 UPNP 服务并且 GNB 启动时使用选项`--es-argv "--upnp"`将明显提升 NAT 穿透的成功概率,详情可以了解 `gnb` 的 `--es-argv "--upnp"` 和 `gnb_es` 的 `--upnp` 选项。 既然监听一个 UDP 端口并启用 UPNP 可以有效提升 NAT 穿透成功的概率,那么通过监听更多 UDP 端口以及在网关上对应建立更多 UPNP 端口映射可以进一步提高节点 NAT 穿透成功的概率,详情可以了解 `--multi-socket` 选项。 在一些网络环境下,充分了解 `gnb` 的 `--es-argv "--upnp"`, `--multi-socket`, `--unified-forwarding` 以及 `gnb_es` 的 `--upnp` 选项的作用可以非常有效提升 GNB 节点的 NAT 穿透的成功率。 使用 `gnb_es` 的 `--dump-address` 选项可以使得已经建立起 P2P 通信的节点的地址信息定期保存到指定的 node cache file 里,当修改配置文件或升级程序或者重启主机需要重新启动 `gnb` 时可以用 `--node-cache-file` 选项指定 node cache file 快速重新建立起通信,要注意的是,对于一部分节点并不一定会成功,详情可以了解 `gnb` 的 `--node-cache-file` 选项 `gnb_es` 的 `--dump-address` 选项。 GNB 节点除了通过 index 节点找到其他节点外还可以通过在 `address.conf` 里配置对端节点的 域名或者动态域名,需要关注的是,仅依靠这种方式去尝试 NAT 穿透效果不如通过 index 节点帮助建立 P2P 通信好。 至此,GNB 为节点的 NAT 穿透做了大量的工作,使得 GNB 的 NAT 穿透的成功率也达到了前所未有的高度,但这依然不够: **GNB Unified Forwarding** 机制可以使得已经建立起 P2P 通讯的节点为未建立起 P2P 通讯的节点转发 IP 分组,并且只要虚拟网络中节点的数量越多,节点之间越容易实现 NAT 穿透并建立起虚拟链路。 通过 **Discover In Lan** 可以让同一个 LAN 下的多个 GNB 节点可以不需要经过 WAN 实现 P2P 通信,与此同时,这可以使未能成功NAT穿透的节点可以通过 **Unified Forwarding**,**Relay Forwarding**,**Standard Forwarding** 让已经成功 NAT 穿透的节点中转 IP 分组,间接实现 P2P 通信。 `gnb_es` 的 `--broadcast-address` 可以让 GNB 节点的将已经和本节点建立起 P2P 通信的节点的地址信息扩散给其他节点,使得这些节点可以获得 GNB 网络内其他节点的更多地址信息以增加 NAT 穿透的成功率。 不得不强调:即使做了许多努力,通过 NAT 穿透建立起 P2P 通信不可能100%的成功率,灵活运用 GNB 提供的机制可以极大的提升 NAT 穿透的成功概率。 # 关于 GNB 的 IPV6 网关/防火墙穿透 提示:在一般情况下,IPV6 地址都是 WAN 地址,但这并不意味着位于网关后面的拥有 IPV6 的主机就不需要穿透,当然这种穿透不能称之为NAT穿透,而是可以被称为网关/防火墙穿透。 由于位于网关的防火墙作用,某些网关(例如OpenWRT route)的防火墙策略默认情况下并不会放行由对端主机主动发起的来自 WAN 的IP分组,这需要两端的主机几乎在同时向对方的端口发送IP分组。 毫无疑问,IPV6的网关/防火墙穿透比IPV4的NAT穿透容易得多,而且成功率可以是100%。 GNB 为 IPV6 的网关/防火墙穿透做了一些工作。 假设一些位于网关后面的 GNB 节点拥有 IPV6地址,而位于 WAN 的 index 节点没有 IPV6 地址,而,这样 index 节点就无法直接得到位于网关后面的 GNB 节点的 IPV6 地址从而没法帮助这些节点建立起通信,要解决这个问题就需要位于网关后面的 GNB 节点获取所在主机的 IPV6 地址后告 index 节点。 假设主机拥有IPV6地址,可以用以下两个命令中的其中一个命令获得本主机的IPV6地址并保存在文件里。 ``` dig -6 TXT +short o-o.myaddr.l.google.com @ns1.google.com | awk -F'"' '{ print $2}' > /tmp/wan6_addr.dump ``` ``` wget http://api.myip.la -q -6 -O /tmp/wan6_addr.dump ``` 以节点 1002 为例 ``` gnb_es -b gnb/conf/1002/gnb.map --resolv --wan-address6-file=/tmp/wan6_addr.dump ``` 通过 `gnb` 和 `gnb_es` 的共享内存,`gnb`进程就能获得本节点所在的 IPV6 地址并上报给 index 节点。 相关信息可以了解`gnb_es` 的 `-b, --ctl_block` 和 `--wan-address6-file` # GNB 的编译构建与运行环境 从安全角度考虑,用户应尽可能自行编译构建 GNB ,如果没有条件编译构建也应尽可能使用来源可靠的二进制包。 GNB 是一个开源的工程,并且在编译构建过程中不需要安装第三方开发库文件,所有源码集中在 `src/` 目录下,所有使用到的第三方开源代码集中在 `libs/` 目录下,因此 GNB 非常容易在各个OS平台上编译构建。 ## FreeBSD ``` make -f Makefile.freebsd ``` ## OpenBSD ``` make -f Makefile.openbsd ``` ## Linux ``` make -f Makefile.linux ``` ## OpenWRT ``` make -f Makefile.openwrt ``` 编译构建运行在 OpenWRT 上的 GNB 需要到 [https://downloads.openwrt.org/releases/](https://downloads.openwrt.org/releases/ "downloads") 下载 对应的 OpenWRT 版本号和硬件平台的 `OpenWRT SDK`。 在下载 `OpenWRT SDK` 前一定要确认 SDK 对应的 OpenWRT 版本号和硬件平台,否则编译出来的程序将无法在目标固件上运行。 访问 OpenWRT 官方网站可以获得更多有关 `OpenWRT SDK` 信息。 一般的,OpenWRT 的固件默认没有安装 kmod-tun,这是Linux上的虚拟网卡内核模块,GNB 在实现三层交换时需要加载这个内核模块。 某些 OpenWRT 固件的文件系统有一些特别的特性,GNB 在这些文件系统上无法通过 **mmap** 系统调用来创建共享内存映射文件 `gnb.map`,而`/etc` 目录恰好就在这些文件系统上,如果用户把节点配置目录放在`/etc`下,默认情况下,GNB 会尝试在节点配置目录下创建共享内存映射文件 `gnb.map`,这会使得进程无法启动,应该通过`-b, --ctl-block`把共享内存映射文件 `gnb.map` 指向例如 `/tmp` 目录下。 如果固件所使用的文件系统是 **ext4** 将不会遇到这个问题。 ## macOS ``` make -f Makefile.Darwin ``` 在 macOS 上编译构建 GNB 需要安装 Xcode。 ## Windows ``` make -f Makefile.mingw_x86_64 ``` `Makefile.mingw_x86_64` 是专门为在 Linux 下用 mingw 编译工具链编译的 Makefile,在 Windows 上也可以使用。 在 Windows 上,运行 GNB 需要安装虚拟网卡,可以在这里下载: [tap-windows](https://github.com/gnbdev/gnb_build/tree/main/if_drv/tap-windows ""downloads"")。 tap-windows 源码所在的仓库:[https://github.com/OpenVPN/tap-windows6](https://github.com/OpenVPN/tap-windows6 "tap-windows6") [wuqiong](https://www.github.com/wuqiong) 为 GNB 在Windows平台上开发了 wintun 虚拟网卡的接口模块。 # 附录 ## gnb的命令行参数 执行`gnb -h`可以看到 gnb 在当前平台所支持的参数。 #### -c, --conf 指定gnb node的目录 #### -n, --nodeid nodeid #### -P, --public-index-service 作为公共索引服务运行 #### -a, --node-address node address #### -r, --node-route node route #### -i, --ifname 指定虚拟网卡的的名字,这在macOS和windows上是无效的,这些系统对虚拟网卡的命名有自己的规则 #### -4, --ipv4-only 禁用ipv6,gnb将不通过ipv6地址收发数据,gnb开启的虚拟网卡不会绑定ipv6地址,由于禁用了ipv6,因此gnb可以设置小于1280的mtu,对于一些限制比较多的网络环境可以利用这个特性尝试使用更小的mtu #### -6, --ipv6-only 禁用ipv4,gnb将不通过ipv4地址收发数据,gnb开启的虚拟网卡不会绑定ipv4地址 #### -d, --daemon 作为daemon进程启动,Windows不支持这个选项 #### -q, --quiet 禁止在控制台输出信息 #### -t, --selftest self test #### -p, --passcode a hexadecimal string of 32-bit unsigned integer, use to strengthen safety #### -U, --unified-forwarding Unified Forwarding "off","force","auto","super","hyper" default:"auto" #### -l, --listen listen address default is "0.0.0.0:9001" #### -b, --ctl-block ctl block mapper file #### -e, --es-argv pass-through gnb_es argv #### -V, --verbose verbose mode #### -T, --trace trace mode #### --node-woker-queue-length node woker queue length #### --index-woker-queue-length index woker queue length #### --index-service-woker-queue index service woker queue length #### --port-detect-start port detect start #### --port-detect-end port detect end #### --port-detect-range port detect range #### --mtu 虚拟网卡的mtu,在比较糟糕的网络环境下ipv4可以设为532,ipv6不可小于1280 #### --crypto 'xor' or 'rc4' or 'none' default is 'xor'; 设定gnb传输数据的加密算法,选择'none'就是不加密,默认是xor使得在CPU运算能力很弱的硬件上也可以有较高的数据吞吐能力。未来会支持aes算法。两个gnb节点必须保持相同的加密算法才可以正常通讯。 #### --crypto-key-update-interval 'hour' or 'minute' or none default is 'none';gnb的节点之间可以通过时钟同步变更密钥,这依赖与节点的时钟必须保持较精确的同步,由于考虑到实际环境中一些节点时钟可能2无法及时同步时间,因此这个选项默认是不启用,如果运行gnb的节点能够保证同步时钟,可以考虑选择一个同步更新密钥的间隔,这可以提升一点通讯的安全性。 #### --multi-index-type 'simple-fault-tolerant' or 'simple-load-balance' default is 'simple-fault-tolerant';如果设置了多个index节点,那么可以选择一个选取index节点的方式,负载均衡或容错模式,这个选项目前还不完善,容错模式只能在交换了通讯密钥的节点之间进行 #### --multi-forward-type 'simple-fault-tolerant' or 'simple-load-balance' default is 'simple-fault-tolerant';如果有多个forward节点,可以选择一个forward节点的方式,负载均衡或在容错模式 #### --socket-if-name example: 'eth0', 'eno1', only for unix-like os;在unix-like系统上可以让gnb的数据通过指定物理网卡发送,这里需要用户输入物理网卡的名字,Windows不支持这个特性,也看不到该选项 #### --address-secure 'hide part of ip address in logs 'on' or 'off' default is 'on' #### --if-dump 'dump the interface data frame 'on' or 'off' default is 'off';把经过gnb开启的虚拟网卡的ip分组在日志中输出,这样方便调试系统 #### --pf-route packet filter route #### --multi-socket 开启多端口探测,在nat穿透端口探测过程中可以较大提升nat穿透成功率 #### --direct-forwarding 'on' or 'off' default is 'on' #### --set-tun 不启动虚拟网卡,这个选项时不需要用root权限去启动进程,用在index和fwd服务 #### --index-worker 'on' or 'off' default is 'on' #### --index-service-worker 'on' or 'off' default is 'on' #### --node-detect-worker 'on' or 'off' default is 'on' #### --set-fwdu0 'on' or 'off' default is 'on' #### --pid-file 指定保存gnb进程id的文件,方便通过脚本去kill进程,如果不指定这个文件,pid文件将保存在当前节点的配置目录下 #### --node-cache-file gnb会定期把成功连通的节点的ip地址和端口记录在一个缓存文件中,gnb进程在退出后,这些地址信息不会消失,重新启动进程时会读入这些数据,这样新启动gnb进程就可能不需通过index 节点查询曾经成功连接过的节点的地址信息 #### --log-file-path 指定输出文件日志的路径,如果不指定将不会产生日志文件 #### --log-udp4 send log to the address ipv4 default is "127.0.0.1:9000" #### --log-udp-type the log udp type 'binary' or 'text' default is 'binary' #### --console-log-level console log level 0-4 #### --file-log-level log file level 0-3 #### --udp-log-level log udp level 0-3 #### --core-log-level core log level 0-3 #### --pf-log-level packet filter log level 0-3 #### --main-log-level main log level 0-3 #### --node-log-level node log level 0-3 #### --index-log-level index log level 0-3 #### --index-service-log-level index service log level 0-3 #### --node-detect-log-level node detect log level 0-4 #### --help ## gnb_es的命令行参数 执行`gnb_es -h`可以看到gnb_es在当前平台所支持的参数 #### -b, --ctl_block ctl block mapper file #### -s, --service service mode #### -d, --daemon daemon #### -L, --discover-in-lan discover in lan #### --upnp upnp #### --resolv resolv #### --dump-address dump address #### --broadcast-address broadcast address #### --pid-file pid file #### --wan-address6-file wan address6 file #### --if-up call at interface up #### --if-down call at interface down #### --log-udp4 send log to the address ipv4 default is "127.0.0.1:9000" #### --log-udp-type the log udp type 'binary' or 'text' default is 'binary' *** https://github.com/gnbdev/opengnb opengnb-ver1.6.0.a/docs/gnb_user_manual_en.md000066400000000000000000001335331500454252100212050ustar00rootroot00000000000000OpenGNB User Manual *Note: Most of the content of this article is translated by Google translate from the Chinese version of the "OpenGNB User Manual", the content of this article is subject to the Chinese version.* # Overview [OpenGNB](https://github.com/gnbdev/opengnb "OpenGNB") is an open source P2P decentralized VPN with extreme intranet penetration capability. GNB is a decentralized network, each node in the network is peer-to-peer, and there is no concept of Server and Client. The ID of each node in each GNB network created by the user is unique, called **nodeid**, which is a 32bit unsigned integer number. GNB nodes can find other GNB nodes through the index node and establish communication. In this process, the role of the GNB index node is similar to the **tracker** in **DNS** and **Bit Torrent**. When GNB communicates with the index node, the public key of **ed25519** and the sha512 digest of `passcode` and **nodeid** are used as unique identifiers. Based on this feature, a GNB index node can provide index services for many GNB networks without Collision conflicts are prone to occur. GNB nodes can also find other GNB nodes through domain name or static IP address or intranet broadcast. GNB enables nodes located in the LAN to successfully establish P2P communication with other nodes through NAT traversal through many methods including but not limited to port detection, upnp, multi-index, multi-socket, etc. In the worst case, when two GNB nodes When a P2P connection cannot be established, the payload can be transferred through other nodes in the network. The operating systems and platforms currently supported by GNB are Linux, Windows10, macOS, FreeBSD, OpenBSD, Raspberry Pi, and OpenWRT. Unless otherwise specified, this document applies to the distributions of these supported platforms and the versions compiled for specific platforms. # deploy GNB ## GNB Public Index node **GNB Public Index node** only provides index service, does not open TUN devices, does not create virtual IP, does not process IP grouping, does not need to be started with root, and is provided by volunteers. The command to start a GNB node in **Public Index** mode can be Start listening on port 9001 by default ``` gnb -P ``` Start listening on port 9002 ``` gnb -P -l 9002 ``` ## Lite Mode of GNB In **Lite Mode**, there is no need to create **ed25519** key pair and configuration file for the node, GNB node can be started by setting command line parameters. The **upnp** option is enabled by default in **Lite Mode**. In the GNB source code, a GNB network with 5 nodes is hardcoded for use in **Lite Mode**. ``` nodeid tun address 1001 10.1.0.1/255.255.0.0 1002 10.1.0.2/255.255.0.0 1003 10.1.0.3/255.255.0.0 1004 10.1.0.4/255.255.0.0 1005 10.1.0.5/255.255.0.0 ``` This greatly simplifies the deployment process. The GNB node in **Lite Mode** generates the communication key through `passcode`, and the security is much lower than the security mode based on **ed25519** asymmetric encryption. The GNB node in **Lite Mode** uses the sha512 digest of `passcode` and **nodeid** as the unique identifier when communicating with the index node. It is assumed that the two GNB networks in **Lite Mode** use the same `passcode` ` and the index node, no doubt this must interfere with each other. The following is a set of commands, which are run on host A and host B respectively to implement virtual networking and need to be executed with **root** on host A ``` gnb -n 1001 -I "$public_index_ip/$port" -l 9001 --multi-socket=on -p 12345678 ``` on host B ``` gnb -n 1002 -I "$public_index_ip/$port" -l 9002 --multi-socket=on -p 12345678 ``` At this point, you can see that the TUN IP on host A is 10.1.0.1, and the TUN IP on host B is 10.1.0.2. At this time, the two nodes can access each other if they establish a connection. Of course, users can set more nodes in **Lite Mode**, which requires understanding `-n`, `-I`, `-a,`, `-r`, `-p`, etc. of `gnb` use of parameters. ## GNB Safe Mode To start GNB in ​​**Safe Mode** mode, you need to set `node.conf` `address.conf` `route.conf` files and **ed25519** public and private keys correctly, these files need to be placed in a directory, the name of the directory Can be **nodeid**. where `address.conf` is optional. Assuming that a node with a nodeid of `1000` is running on the WAN as an index node, and other GNB nodes find the `1000` node through the configuration of `address.conf`, then in general, the `1000` node does not need `address.conf` . If multiple GNB nodes are created, the configuration directories for these nodes can be placed under `gnb/conf/` for easy management. ### Directory Structure Take nodes `1001` `1002` `1003` as an example, the configuration directories of these nodes are as follows ``` gnb / conf / 1001 / gnb/conf/1001/node.conf gnb/conf/1001/address.conf gnb/conf/1001/route.conf gnb/conf/1001/security/1001.private gnb/conf/1001/security/1001.public gnb/conf/1001/ed25519/1002.public gnb/conf/1001/ed25519/1003.public gnb/conf/1001/scripts ``` ``` gnb / conf / 1002 / gnb/conf/1002/node.conf gnb/conf/1002/address.conf gnb/conf/1002/route.conf gnb/conf/1002/security/1002.private gnb/conf/1002/security/1002.public gnb/conf/1002/ed25519/1001.public gnb/conf/1002/ed25519/1003.public gnb/conf/1002/scripts ``` ``` gnb / conf / 1003 / gnb/conf/1003/node.conf gnb/conf/1003/address.conf gnb/conf/1003/route.conf gnb/conf/1003/security/1003.private gnb/conf/1003/security/1003.public gnb/conf/1003/ed25519/1001.public gnb/conf/1003/ed25519/1002.public gnb/conf/1003/scripts ``` Assuming that the configuration directories of these nodes have been deployed to different hosts, the commands to start the `1001` `1002` `1003` nodes can be: ``` gnb -c gnb/conf/1001 gnb -c gnb/conf/1002 gnb -c gnb/conf/1003 ``` The `scripts/` directory stores scripts that are called after the virtual network card is started/closed, which is used for user-defined routing and firewall instructions. `security/` stores the **ed25519** public and private keys of this node, and `ed25519/` stores the public keys of other nodes. ### key exchange In **Safe Mode**, GNB nodes exchange communication keys through asymmetric encryption (ed25519), which is the basis of GNB node communication, so it is necessary to create a set of public and private keys for each GNB node for communication. The public and private keys are named with the UUID of the node as the file name, .private and .public as the file suffix. The public and private key files of the node whose UUID is 1001 should be `1001.public` `1001.private` GNB provides a command line tool named `gnb_crypto` for generating public and private keys, The command to create **ed25519** public and private keys for `1001` `1002` `1003` nodes is: `gnb_crypto -c -p 1001.private -k 1001.public` `gnb_crypto -c -p 1002.private -k 1002.public` `gnb_crypto -c -p 1003.private -k 1003.public` To exchange public keys, is to put these **ed25519** public and private keys into the correct directory. On the node with **nodeid** `1001`: There should be `1001.private` `1001.public` in the `gnb/conf/1001/security/` directory There should be `1002.public` `1003.public` in the `gnb/conf/1001/ed25519/` directory On the node with nodeid `1002`: There should be `1002.private` `1002.public` in the `gnb/conf/1002/security/` directory There should be `1001.public` `1003.public` in the `gnb/conf/1002/ed25519/` directory On the node with nodeid `1003`: There should be `1003.private` `1003.public` in the `gnb/conf/1003/security/` directory There should be `1001.public` `1002.public` in the `gnb/conf/1003/ed25519/` directory On the basis of asymmetric encryption, nodes under the same GNB network can also set the same `passcode` to protect the communication key. For information about GNB communication keys, please refer to the description of `--crypto` `--crypto-key-update-interval` `--passcode`. ## GNB payload forwarding - **Direct Forwarding** P2P communication between nodes; under normal circumstances, nodes located on the WAN must be able to establish P2P communication with other nodes, and nodes located in the LAN to establish P2P communication with nodes in other LANs must go through NAT penetration; - **Unified Forwarding** automatically forwards IP packets through nodes that have established P2P communication, and multiple nodes retransmit IP packets; - **Relay Forwarding** highly custom relay routing, IP packets will be encrypted before being sent to the next relay point, the relevant settings are in `route.conf`; - **Standard Forwarding** Nodes that cannot establish P2P communication after exhausting all strategies can relay IP packets through forward nodes located on the public network ### node.conf configuration file The following is an example of `node.conf`: ``` nodeid 1001 listen 9001 ``` `node.conf` is used to store the configuration information of the node, the format is as follows ``` nodeid $nodeid listen $listen_port ``` or ``` nodeid $nodeid listen ip_address:$listen_port ``` GNB supports IPV6 and IPV4. There are some options worth paying attention to, which can greatly improve GNB's NAT traversal capabilities: ``` es-argv "--upnp" ``` Try turning on upnp to make it easier for IP packets from the WAN to be passed in. ``` multi-socket on ``` Open more UDP listening ports and increase the probability of successful port detection for NAT penetration. After `multi-socket` is set to on, 4 additional random UDP ports will be opened in addition to the original `listen` port. If you want to monitor the specified port additionally, you can use multiple `listen` setting items, GNB Supports listening on 5 address ports with `listen` or listening on 5 IPV6 addresses and ports with `listen6` and listening on 5 IPV4 address ports with `listen4`. The configuration items supported by `node.conf` correspond to the gnb command line parameters one by one. The currently supported configuration items are: ``` ifname nodeid listen listen6 listen4 ctl-block multi-socket disabled-direct-forward ipv4-only ipv6-only passcode quiet daemon mtu set-tun address-secure node-worker index-worker index-service-worker node-detect-worker port-detect-range port-detect-start port-detect-end pid-file node-cache-file log-file-path log-udp4 log-udp-type console-log-level file-log-level udp-log-level core-log-level pf-log-level main-log-level node-log-level index-log-level detect-log-level es-argv ``` ### route.conf file The data packet communicated between GNB nodes is called **gnb payload**, a routing table shared by all nodes in the network, the configuration file is `route.conf`, its role is to tell the GNB core how to "route" these Contains the **gnb payload** of the IP packet. Each routing configuration item occupies one line. There are two types of routing configuration items, **forward** and **relay**, which are used to set the way that the payload of the local node reaches the peer node. The following is an example of `route.conf` type forward: ``` 1001|10.1.0.1|255.255.255.0 1002|10.1.0.2|255.255.255.0 1003|10.1.0.3|255.255.255.0 ``` Each line in the configuration file is a description of a node in the following format ``` $nodeid|$tun_ipv4|$tun_netmask ``` The meaning of each configuration item is as follows: `$nodeid` UUID of the node `$tun_ipv4` IPV4 address of the virtual network card `$tun_netmask` The subnet mask of the IPV4 address of the virtual network interface #### Direct forwarding The default communication between nodes is point-to-point, which is called **Direct forwarding**, that is, IP packets are sent directly to the IP address and port of the peer node. For example, in `route.conf` there is a line ``` 1001|10.1.0.1|255.255.255.0 ``` When GNB processes an IP packet whose destination address is 10.1.0.1, it determines that this IP packet needs to be encrypted and encapsulated with the communication key of the node whose **nodeid** is 1001, and sent to the node 1001 as **gnb payload** , this process we call **Direct forwarding**. #### Standard Forwarding If there is no P2P communication between nodes, the **gnb payload** can be forwarded through the **forward** node with the **f** attribute defined in `address.conf`. This communication method is called * *Standard Forwarding** example: `address.conf` ``` if|1001|x.x.x.x|9001 ``` The 1001 node in the above example is an **idnex** node and also a **forward** node. #### Relay Forwarding **Relay Forwarding** relays the **gnb payload** through a clear custom relay path, and the **gnb payload** will be encrypted again by the relay node during the relaying process. Due to end-to-end encryption, the **forward node** and **relay node** nodes cannot obtain the plaintext of the IP packets in the **gnb payload** at both ends of the communication. To set a relay node for the destination node, you can set up to 8 relay routes for a peer node, and each relay route can have up to 5 relay nodes. Here are some examples of `route.conf` type relay: ``` 1006|1003 1006|auto,static ``` The function of this group of routes is: when the current node cannot establish P2P communication with the 1006 node, the IP packet sent to the 1006 node will be relayed through the 1003 node. ``` 1006|1003,1004,1005 1006|force,static ``` The meaning of this group of routes is: the IP packets sent by the current node to the 1006 node are forced to be relayed to the 1006 node through 1005, 1004, 1003 in sequence. ``` 1006|1003,1005 1006|1005,1004 1006|1005,1003 1006|force,balance ``` The role of this group of routes is: there are 3 relay routes from the current node to the 1006 node, and the strategy for selecting routes when sending IP packets is load balancing. The relevant setting items are formatted as follows: ``` $nodeid|$relay_nodeid3,$relay_nodeid2,$relay_nodeid1 $nodeid|$relay_mode ``` The path for the payload of the local node to reach the peer node through the relay node is local_node => relay_node1 => relay_node2 => relay_node3 => dst_node, and the path from dst_node to local_node is determined by the route.conf configuration of the peer dst_node. `$relay_mode` can be **auto**, **force**, **static**, **balance** **auto** Forward through the preset relay route when the destination node cannot communicate point-to-point and there is no forward node forwarding **force** Force communication with the destination node to go through the relay route **static** When a destination node has multiple relay routes, use the first relay route **balance** When a destination node has multiple relay routes, the relay route is selected in a load balancing manner ### address.conf file `address.conf` is used to configure the properties of the node and the public IP address and port. The following is an example of `address.conf`: ``` i|0|a.a.a.a|9001 if|1001|b.b.b.b|9001 n|1002|c.c.c.c|9001 ``` `aaaa` `bbbb` `cccc` in the file represents the IP address of the physical network card of the node, which needs to be filled in according to the actual situation. Each line in the configuration file is a description of an address, and the format is as follows ``` $attrib|$nodeid|$ipv4/$ipv6/$hostname|$port ``` **$attrib** Node attributes, represented by a set of characters, i means that this node is an index node; f means that this node is a forward node; n means that this node is a normal node; s is a silent (silence) node, If the local node contains the s attribute, it will not communicate with the index node, nor will it respond to ping-pong and address detection requests to expose the local ip address **$nodeid** The nodeid of the node, corresponding to **$nodeid** in `route.conf` **$ipv6** IPV6 address of the GNB node **$ipv4** IPV4 address of the GNB node **$hostname** The domain name of the GNB node **$port** GNB node service port If a node has multiple IP addresses, it needs to be configured in multiple lines according to the format. GNB will use the **GNB node ping-pong** protocol to measure which IP address of the node has lower latency, and then send IP packets. When data is sent, it is automatically sent to a low-latency address. The `gnb` process does not perform domain name interpretation on **$hostname** in `address.conf`, but is processed asynchronously by `gnb_es`, see the `--resolv` option of `gnb_es` for related information. As mentioned above, the function of the index node is similar to the **tracker** in **DNS** and **Bit Torrent**. If a group of GNB nodes that do not know each other's IP address and port are sent to the same index The node submits its own IP address and port, then these GNB nodes can query the peer node's IP address and port from the index through the peer node's public key. The **i** attribute is required in the **$attrib** of the index node in `address.conf`. The GNB index protocol allows not to verify the digital signature of the message in the process of submitting and querying the IP address port of the node, that is, the index node allows the digital signature of the message to submit and query the IP not to be verified, and the node does not respond to the message of the query IP from the index node. Verify digital signatures. **GNB Public Index node** The corresponding **nodeid** in `address.conf` can be set to **0**, no need to set the "route" rule in `route.conf`, the following is An example of a **GNB Public Index node**: ``` i|0|a.a.a.a|9001 ``` The forward node **$attrib** is set to **f**, **$nodeid** cannot be set to **0**, and must be bound to nodeid as a configuration item in `route.conf`, gnb forward Protocol-related messages must be sent with the digital signature of the verification node, that is, the forward node and the node forwarding the message through the forward node must exchange public keys with each other. The forward node can transfer IP packets for GNB nodes that cannot directly access each other. These nodes are usually deployed in the intranet and do not have a fixed public network ip, and they have exhausted all methods to achieve NAT penetration and achieve point-to-point communication. The content of the communication between the two nodes cannot be decrypted. Of course, users can use a GNB node as the index node and forward node in the GNB network, and can also provide index services for other GNB networks. The following is an example: ``` if|1001|b.b.b.b|9001 ``` In `address.conf` there can be multiple index nodes and forward nodes, and can be passed through `--multi-index-type` `--multi-forward-type` Set load balancing and fault tolerance mode, Assuming that a GNB node may have multiple NATed IP addresses at the same time after very complex address translation in the LAN, that is, the operator may choose different gateway exits according to the destination address of the host in the LAN accessing the WAN. If `address.conf` has multiple Index nodes, then in NAT traversal, the peer GNB node may know more addresses and ports of the node, thereby increasing the success rate of NAT traversal to establish P2P communication. ## GNB Unified Forwarding Under the complex NAT mechanism, the nodes located in the LAN cannot ensure 100% successful NAT traversal, but there will always be some nodes that can successfully achieve NAT traversal and establish P2P communication. The **GNB Unified Forwarding** mechanism can make The nodes that have established P2P communication forward IP packets to the nodes that have not established P2P communication. Each node in the GNB network periodically announces the id of the node that has established P2P communication with itself in the network, which enables each node in the network to know which transit nodes are available when sending data to another node. Take a GNB network with three nodes A, B, and C as an example: A and C, B and C all establish P2P communication, but A and B cannot establish P2P communication due to the complex NAT mechanism, through **GNB Unified Forwarding** mechanism, A and B can forward IP packets through C. According to the mechanism of **GNB Unified Forwarding**, as long as the number of nodes in the virtual network is more, it is easier to achieve NAT traversal between nodes and establish a virtual link. The IP packets sent to the target node can be forwarded by multiple transit nodes at the same time. The IP packets that reach the target node first will be written to the virtual network card. GNB maintains a 64-bit timestamp and timestamp queue for each target node to ensure repeated transmission. IP packets are discarded, so the **GNB Unified Forwarding** feature can be used to speed up TCP retransmissions in some cases. ### GNB Unified Forwarding Operating mode `auto` When the two nodes A and B cannot establish P2P communication, automatically transfer IP packets through the nodes (which can be in LAN) that have established P2P communication with A and B respectively. `super` Regardless of whether the two nodes A and B have established P2P communication, in the process of sending ip packets, multiple nodes that have established P2P communication with A and B, respectively, retransmit and transfer TCP type ip packets. `hyper` Regardless of whether the two nodes A and B have established P2P communication, in the process of sending ip packets, all types of ip packets are retransmitted and relayed through multiple nodes that have established P2P communication with A and B respectively. To learn more about **Unified Forwarding**, see the `-U, --unified-forwarding` option of `gnb` ### About Discover In Lan **Discover In Lan** enables GNB nodes to discover other GNB nodes in the LAN through broadcast, which enables GNB nodes under the same LAN to establish communication without first going through WAN for NAT penetration. **Discover In Lan** is implemented in `gnb_es`. In order for `gnb_es` to always listen for broadcast packets from other nodes in the LAN, `gnb_es` must be started as service or daemon with the `-L, --discover-in-lan` option. The following node 1002 is an example ``` gnb_es -s -L -b gnb / conf / 1002 / gnb.map ``` `gnb.map` is a shared memory mapping file created by the `gnb` process. If not specified, this mapping file will be created in the node's configuration directory (`gnb/conf/1002/`); through this shared memory , `gnb_es` can pass the information from other GNB nodes monitored in the LAN to the gnb process; at the same time, `gnb_es` also regularly broadcasts the information of its own node in the LAN so that it can be discovered by other nodes in the LAN. In the process of deploying GNB nodes, users will find that in some cases, some GNB nodes in the same LAN can successfully NAT traverse and successfully establish P2P communication with nodes in another LAN, while some nodes fail to establish P2P communication. Success, with the help of **Discover In Lan**, not only can more nodes be connected more easily, but also the nodes that have successfully NAT traversed can help other nodes under the same LAN to forward IP packets. For more information about **Discover In Lan**, you can refer to `-b, --ctl-block` of `gnb`, and `-s, --service` `-d, - of `gnb_es` -daemon` `-L, --discover-in-lan` options. ### About net to net Generally speaking, VPN can combine several computers into a network by establishing a virtual link, or allow one computer to access a network through a virtual link, and can also connect two or more computers through a virtual link. The network forms a large virtual network, so that computers scattered in different networks can access each other. This kind of architecture that integrates several networks into a virtual network through the virtual link of VPN is called ** net to net **. GNB makes the deployment of ** net to net ** very easy. With GNB's powerful NAT traversal capability, GNB can easily combine several LANs located in different places to form a virtual network, and most of the time one of these LANs is a virtual network. There is P2P direct communication between the two networks without the need for the central node to transfer, so that the communication between the networks is not limited by the bandwidth of the central node. Assuming that there are two remote **LAN A** and **LAN B** accessing the Internet through NAT, and the gateways of these two LANs are both OpenWRT Routers, then only two GNB nodes need to be deployed on the OpenWRT Router, with the help of WAN On the GNB index node to achieve NAT penetration, the hosts in **LAN A** and **LAN B** can access each other. Assuming that there are two remote **LAN A** and **LAN B** accessing the Internet through NAT, and the gateways of these two LANs are both OpenWRT Routers, then only two GNB nodes need to be deployed on the OpenWRT Router to traverse the Internet through NAT. By establishing P2P communication, hosts in **LAN A** and **LAN B** can access each other. In this process, it is usually necessary to have a GNB index node located on the WAN to help the two GNB nodes find each other. In the following example, in order to ensure that the two nodes can communicate even if the NAT traversal is unsuccessful, it is possible to deploy A forward node also provides index service. Thus, a total of 3 GNB nodes need to be deployed: **nodeid**=1001 on WAN, as index and forward node, IP= xxxx port = 9001 **nodeid**=1002 on OpenWRT Router on **LAN A**, NetWork=192.168.0.0/24 **nodeid**=1003 on OpenWRT Router on **LAN B**, NetWork=192.168.1.0/24 set **node 1001** `conf/1001/node.conf` ``` nodeid 1001 listen 9001 ``` `conf/1001/route.conf` ``` 1001|10.1.0.1|255.255.255.0 1002|10.1.0.2|255.255.255.0 1003|10.1.0.3|255.255.255.0 ``` Set **node 1002** in **LAN A** `conf/1002/node.conf` ``` nodeid 1002 listen 9002 multi-socket on es-argv --upnp ``` `conf/1002/route.conf` ``` 1001|10.1.0.1|255.255.255.0 1002|10.1.0.2|255.255.255.0 1003|10.1.0.3|255.255.255.0 1003|192.168.1.0|255.255.255.0 ``` `conf/1002/address.conf` ``` if|1001|x.x.x.x|9001 ``` xxxx is the WAN IP of node 1001, which needs to be filled in according to the actual situation. `conf/1002/scripts/if_up_linux.sh` ``` ip route add 192.168.1.0/24 via 10.1.0.3 ``` The function of this routing instruction is: when the host in **LAN A** wants to send the IP packet whose destination address is `192.168.1.0/24`, because the network of **LAN A** is `192.168.0.0/24` `, so these purpose is `192.168.1.0/24` IP packets will be sent to the default gateway OpenWRT Router, because this routing rule is set, these IP packets will be forwarded to the TUN device to be captured and encapsulated by the GNB process as ** The gnb payload** is finally sent to **node 1003**. Undoubtedly, there needs to be a similar routing directive on **node 1003** so that IP packets destined to `192.168.0.0/24` can reach **node 1003** GNB processes are eventually sent to **node 1002** on. Set **node 1003** in **LAN B** `conf/1003/node.conf` ``` nodeid 1003 listen 9003 multi-socket on es-argv --upnp ``` `conf/1003/route.conf` ``` 1001|10.1.0.1|255.255.255.0 1002|10.1.0.2|255.255.255.0 1003|10.1.0.3|255.255.255.0 1002|192.168.0.0|255.255.255.0 ``` `conf/1003/address.conf` ``` if|1001|x.x.x.x|9001 ``` `conf/1003/scripts/if_up_linux.sh` ``` ip route add 192.168.0.0/24 via 10.1.0.2 ``` Usually, OpenWRT has some firewall rules by default, which may cause the IP packets forwarded by GNB to the host in the current LAN to be blocked. Therefore, OpenWRT needs to be detected here. Generally, the Forward option in the firewall should be set to accept. , and the Forwardings related to Wan are set to accept. After confirming that the configuration is correct, you can start **node 1001** first, then **node 1002** and **node 1003**, so that **node 1001** can be the first time **node 1002** And **node 1003** provides index service. After starting **node 1001**, **node 1002** and **node 1003**, you can first try the virtual IPs corresponding to these three GNB nodes, namely `10.1.0.1` `10.1.0.2` ` 10.1.0.3` can successfully pass the ping test. If all goes well, you can try to ping a host on **LAN B** from a host in **LAN A**. For example, ping the host whose IP is `192.168.0.2` under **LAN A** and ping the host whose IP is `192.168.1.2` under **LAN B**, no doubt, you can also test in the opposite direction . At this point, if it is found that the virtual IPs corresponding to the three GNB nodes can pass the ping test, but the hosts in the two LANs cannot pass the ping test, then you can go back to the previous steps to check the firewall rules on OpenWRT and the detection host. firewall rules. # About GNB's NAT traversal The ultimate NAT penetration capability may be the most exciting feature of GNB, but it is not the whole of GNB. There are many valuable features of GNB to be explored by users. In a complex network environment, it is sometimes difficult to establish P2P communication with other nodes through successful NAT traversal. In order to improve the probability of successful NAT traversal of a node, it is necessary to introduce NAT (Network Address Translation) and GNB in ​​NAT traversal in detail. work done. Usually, for some hosts that access the Internet through NAT in the LAN, the process of NAT (Network Address Translation) will involve, but not limited to, such as routing equipment in the LAN, network structure, network equipment used by operators, network Architecture, NAT strategy and many other network environments are almost "black box". The IP address of a packet may undergo multiple translations, and there may be multiple egress gateways. These are uncertain factors in the NAT traversal process. **Don't talk about the white paper, who known? who care?** **Don't talk about the type of NAT, I don‘t f*cking care** **What GNB has to do, just try it's best to traverse the NAT** There is no doubt that GNB was inspired by **Bit Torrent** these P2P software, since two hosts in different LANs accessing the Internet through NAT can establish P2P communication for transferring file data blocks, then it means that This mode can also be used to transmit IP packets for virtual network cards. GNB uses all kinds of strategies to promote the success of NAT traversal. Among these strategies, some strategies are very effective, some are not very effective, and some strategies are effective in some situations and may not be effective in other situations. First, the local node obtains the WAN addresses and ports of other nodes by communicating and exchanging information with the index node and tries to contact these nodes; In fact, some nodes will use more than one WAN address to access the Internet after going through NAT. GNB supports exchanging information with multiple index nodes at the same time, so that there is a chance to discover more WAN addresses of peer nodes. For peer nodes that are defined in `route.conf` and have not established P2P communication, the GNB process will periodically query the index node for the WAN address ports of these nodes, and try to initiate communication. GNB will detect a small range of ports for the peer node that has obtained the WAN address but has not established P2P communication. GNB also has a special thread to periodically detect a wide range of ports for orders that fail to establish P2P communication. Like most P2P software such as **Bit Torrent**, GNB will also try to establish address-port mapping on the egress gateway through UPNP to improve the success rate of NAT penetration. It should be noted that if a LAN has multiple hosts deploying GNB nodes and enabling UPNP, these nodes should not listen to the same port, which will cause conflicts when the gateway establishes UPNP port mapping. If the gateway where the host is located supports and enables the UPNP service and the option `--es-argv "--upnp"` is used when GNB is started, the success probability of NAT penetration will be significantly improved. For details, see `--es- of `gnb` argv "--upnp"` and the `--upnp` option for `gnb_es`. Since monitoring a UDP port and enabling UPNP can effectively improve the probability of successful NAT penetration, then by monitoring more UDP ports and establishing more UPNP port mappings on the gateway, the probability of successful NAT penetration can be further improved. `--multi-socket` option. In some network environments, fully understanding the functions of `--es-argv "--upnp"` of `gnb`, `--multi-socket` and `--upnp` of `gnb_es` can be very effective in improving GNB The success rate of the node's NAT penetration. In some network environments, fully understand `--es-argv "--upnp"` of `gnb`, `--multi-socket`, `--unified-forwarding` and `--upnp` of `gnb_es` The option can effectively improve the success rate of NAT traversal of GNB nodes. Using the `--dump-address` option of `gnb_es` can make the address information of the nodes that have established P2P communication regularly saved in the specified node cache file, when modifying the configuration file or upgrading the program or restarting the host, you need to restart `gnb `, you can use the `--node-cache-file` option to specify the node cache file to quickly re-establish communication. It should be noted that some nodes may not be successful. For details, you can learn about `--node- of `gnb` The `--dump-address` option of the cache-file` option `gnb_es`. In addition to finding other nodes through the index node, GNB nodes can also configure the domain name or dynamic domain name of the peer node in `address.conf`. It should be noted that only relying on this method to try NAT penetration is not as effective as using the index node. Good for helping to establish P2P communication. So far, GNB has done a lot of work for NAT penetration of nodes, and the success rate of NAT penetration has reached an unprecedented height, but this is still not enough. The **GNB Unified Forwarding** mechanism enables nodes that have established P2P communication to forward IP packets to nodes that have not established P2P communication, and as long as the number of nodes in the virtual network is greater, the easier it is to achieve NAT penetration between nodes. A virtual link is established. Through **Discover In Lan**, multiple GNB nodes under the same LAN can realize P2P communication without going through WAN. At the same time, this allows nodes that fail NAT penetration to pass through **relay** The method allows the nodes that have successfully NAT traversed to transfer IP packets to indirectly realize P2P communication. The `--broadcast-address` of `gnb_es` allows the GNB node to spread the address information of the node that has established P2P communication with this node to other nodes, so that these nodes can obtain more address information of other nodes in the GNB network To increase the success rate of NAT penetration. It has to be emphasized that even if a lot of efforts are made, it is impossible to establish a 100% success rate for P2P communication through NAT penetration. The flexible use of the mechanism provided by GNB can greatly improve the probability of success. # About IPV6 gateway/firewall penetration of GNB In general, IPV6 addresses are all WAN addresses, but this does not mean that hosts with IPV6 behind the gateway do not need to penetrate. Of course, this penetration cannot be called NAT penetration, but can be called NAT penetration. For gateway/firewall penetration. Due to the role of the firewall at the gateway, the firewall policy of some gateways (such as OpenWRT route) does not allow IP packets from the WAN initiated by the opposite host by default. Send IP packets. There is no doubt that IPV6 gateway/firewall penetration is much easier than IPV4 NAT penetration, and the success rate can be 100%. GNB does some work for IPV6 gateway/firewall penetration. Assuming that some GNB nodes behind the gateway have IPV6 addresses, while the index nodes located in the WAN do not have IPV6 addresses, and the index nodes cannot directly obtain the IPV6 addresses of the GNB nodes behind the gateway and thus cannot help these nodes to establish communication. To solve this problem, the GNB node behind the gateway needs to obtain the IPV6 address of the host where it is located and report it to the index node. Assuming that the host has an IPV6 address, one of the following two commands can be used to obtain the IPV6 address of the host and save it in a file. ``` dig -6 TXT +short o-o.myaddr.l.google.com @ns1.google.com | awk -F'"' '{ print $2}' > /tmp/wan6_addr.dump ``` ``` wget http://api.myip.la -q -6 -O /tmp/wan6_addr.dump ``` Take node 1002 as an example ``` gnb_es -b gnb/conf/1002/gnb.map --resolv --wan-address6-file=/tmp/wan6_addr.dump ``` Through the shared memory of `gnb` and `gnb_es`, the `gnb` process can obtain the IPV6 address of this node and report it to the index node. For related information, see `-b, --ctl_block` and `--wan-address6-file` of `gnb_es` # GNB build and run environment From a security point of view, users should compile and build GNB by themselves as much as possible. If there is no conditional compilation and build, they should use binary packages from reliable sources as much as possible. GNB is an open source project, and there is no need to install third-party development library files during the compilation and construction process. All source code is concentrated in the `src/` directory, and all third-party open source code used is concentrated in the `libs/` directory. Therefore, GNB is very easy to compile and build on various OS platforms. ## FreeBSD ``` make -f Makefile.freebsd ``` ## OpenBSD ``` make -f Makefile.openbsd ``` ## Linux ``` make -f Makefile.linux ``` ## OpenWRT ``` make -f Makefile.openwrt ``` To compile and build GNB running on OpenWRT, you need to go to [https://downloads.openwrt.org/releases/](https://downloads.openwrt.org/releases/ "downloads") to download the corresponding OpenWRT version number and hardware platform `OpenWRT SDK`. Before downloading the `OpenWRT SDK`, be sure to confirm the OpenWRT version number and hardware platform corresponding to the SDK, otherwise the compiled program will not run on the target firmware. Visit the official OpenWRT website for more information about the `OpenWRT SDK`. Generally, kmod-tun is not installed by default in the firmware of OpenWRT, which is a virtual network card kernel module on Linux. GNB needs to load this kernel module when implementing Layer 3 switching. Some OpenWRT firmware filesystems have some special features, GNB cannot create shared memory mapped file `gnb.map` through **mmap** system call on these filesystems, and `/etc` directory happens to be in these On the file system, if the user puts the node configuration directory under `/etc`, by default, GNB will try to create the shared memory map file `gnb.map` in the node configuration directory, which will make the process unable to start. `-b, --ctl-block` Point the shared memory map file `gnb.map` to eg `/tmp` directory. This problem will not be encountered if the file system used by the firmware is **ext4**. ## macOS ``` make -f Makefile.Darwin ``` Compiling and building GNB on macOS requires Xcode to be installed. ## Windows ``` make -f Makefile.mingw_x86_64 ``` `Makefile.mingw_x86_64` is a Makefile specially compiled with mingw compiling toolchain under Linux, Also available on Windows. On Windows, running GNB requires installing a virtual network card, which can be downloaded here: [tap-windows](https://github.com/gnbdev/gnb_build/tree/main/if_drv/tap-windows ""downloads""). The repository where tap-windows source code is located: [https://github.com/OpenVPN/tap-windows6](https://github.com/OpenVPN/tap-windows6 "tap-windows6") # Appendix ## gnb command line arguments Execute `gnb -h` to see the parameters supported by gnb on the current platform. #### -c, --conf Specify the directory of the gnb node #### -n, --nodeid nodeid #### -P, --public-index-service Runs as a public indexing service #### -a, --node-address node address #### -r, --node-route node route #### -i, --ifname Specify the name of the virtual network card, which is invalid on macOS and Windows, these systems have their own rules for naming virtual network cards #### -4, --ipv4-only Disable ipv6, gnb will not send and receive data through ipv6 address, the virtual network card enabled by gnb will not bind ipv6 address, because ipv6 is disabled, gnb can set mtu less than 1280, this feature can be used for some network environments with more restrictions try with a smaller mtu #### -6, --ipv6-only Disable ipv4, gnb will not send and receive data through the ipv4 address, and the virtual network card enabled by gnb will not bind the ipv4 address #### -d, --daemon Started as a daemon process, Windows does not support this option #### -q, --quiet Disable output to console #### -t, --selftest self test #### -p, --passcode a hexadecimal string of 32-bit unsigned integer, use to strengthen safety #### -l, --listen listen address default is "0.0.0.0:9001" #### -b, --ctl-block ctl block mapper file #### -e, --es-argv pass-through gnb_es argv #### -V, --verbose verbose mode #### --node-woker-queue-length node woker queue length #### --index-woker-queue-length index woker queue length #### --index-service-woker-queue index service woker queue length #### --port-detect-start port detect start #### --port-detect-end port detect end #### --port-detect-range port detect range #### --mtu The mtu of the virtual network card can be set to 532 for ipv4 and 1280 for ipv6 in a poor network environment. #### --crypto 'xor' or 'rc4' or 'none' default is 'xor'; Set the encryption algorithm of gnb transmission data, select 'none' means no encryption, the default is xor so that it can also be used on hardware with weak CPU computing power Higher data throughput. The aes algorithm will be supported in the future. Two gnb nodes must maintain the same encryption algorithm for normal communication. #### --crypto-key-update-interval 'hour' or 'minute' or none default is 'none'; the key can be changed between gnb nodes through clock synchronization, which depends on the fact that the clock of the node must be synchronized more accurately, because some node clocks in the actual environment are considered It may not be possible to synchronize the time in time, so this option is not enabled by default. If the node running gnb can guarantee the synchronization of the clock, you can consider selecting an interval for synchronizing and updating the key, which can improve the security of communication. #### --multi-index-type 'simple-fault-tolerant' or 'simple-load-balance' default is 'simple-fault-tolerant'; if multiple index nodes are set, you can choose a way to select index nodes, load balancing or fault-tolerant mode, this The options are not yet perfect, and the fault-tolerant mode can only be performed between nodes that have exchanged communication keys #### --multi-forward-type 'simple-fault-tolerant' or 'simple-load-balance' default is 'simple-fault-tolerant'; if there are multiple forward nodes, you can choose a forward node method, load balancing or in fault-tolerant mode #### --socket-if-name example: 'eth0', 'eno1', only for unix-like os; on unix-like systems, gnb data can be sent through the specified physical network card, where the user needs to enter the name of the physical network card. Windows does not support this feature, and also I don't see this option #### --address-secure 'hide part of ip address in logs 'on' or 'off' default is 'on' #### --if-dump 'dump the interface data frame 'on' or 'off' default is 'off'; group the ip of the virtual network card opened by gnb and output it in the log, which is convenient for debugging the system #### --pf-route packet filter route #### --multi-socket When multi-port detection is enabled, the success rate of NAT penetration can be greatly improved in the process of NAT penetration port detection. #### --direct-forwarding 'on' or 'off' default is 'on' #### --set-tun Do not start the virtual network card, this option does not require root privileges to start the process, used in index and fwd services #### --index-worker 'on' or 'off' default is 'on' #### --index-service-worker 'on' or 'off' default is 'on' #### --node-detect-worker 'on' or 'off' default is 'on' #### --set-fwdu0 'on' or 'off' default is 'on' #### --pid-file Specify the file that saves the gnb process id, which is convenient to kill the process through a script. If this file is not specified, the pid file will be saved in the configuration directory of the current node #### --node-cache-file gnb will regularly record the IP address and port of the successfully connected node in a cache file. After the gnb process exits, these address information will not disappear, and the data will be read when the process is restarted, so that it is possible to start the gnb process. There is no need to query the address information of the nodes that have been successfully connected through the index node #### --log-file-path Specify the path of the output file log, if not specified, no log file will be generated #### --log-udp4 send log to the address ipv4 default is "127.0.0.1:9000" #### --log-udp-type the log udp type 'binary' or 'text' default is 'binary' #### --console-log-level log console level 0-3 #### --file-log-level log file level 0-3 #### --udp-log-level log udp level 0-3 #### --core-log-level core log level 0-3 #### --pf-log-level packet filter log level 0-3 #### --main-log-level main log level 0-3 #### --node-log-level node log level 0-3 #### --index-log-level index log level 0-3 #### --index-service-log-level index service log level 0-3 #### --node-detect-log-level node detect log level 0-3 #### --help ## Command line arguments for gnb_es Execute `gnb_es -h` to see the parameters supported by gnb_es on the current platform #### -b, --ctl_block ctl block mapper file #### -s, --service service mode #### -d, --daemon daemon #### -L, --discover-in-lan discover in lan #### --upnp upnp #### --resolv resolv #### --dump-address dump address #### --broadcast-address broadcast address #### --pid-file pid file #### --wan-address6-file wan address6 file #### --if-up call at interface up #### --if-down call at interface down #### --log-udp4 send log to the address ipv4 default is "127.0.0.1:9000" #### --log-udp-type the log udp type 'binary' or 'text' default is 'binary' *** https://github.com/gnbdev/opengnb opengnb-ver1.6.0.a/examples/000077500000000000000000000000001500454252100157165ustar00rootroot00000000000000opengnb-ver1.6.0.a/examples/node_config_example/000077500000000000000000000000001500454252100217035ustar00rootroot00000000000000opengnb-ver1.6.0.a/examples/node_config_example/address.conf000066400000000000000000000000301500454252100241700ustar00rootroot00000000000000i|0|101.32.178.3|9001 opengnb-ver1.6.0.a/examples/node_config_example/node.conf000066400000000000000000000004431500454252100235000ustar00rootroot00000000000000#setup uuid for node #nodeid $nodeid #setup listen udp port #listen $port #use multi socket to increase gnb nat traversal success rate #multi-socket on #pass-through argv "--upnp" to gnb_es try to set upnp #es-argv --upnp #set maximum transmission unit(MTU) for the tun device #mtu 1450 opengnb-ver1.6.0.a/examples/node_config_example/route.conf000066400000000000000000000002151500454252100237060ustar00rootroot000000000000001001|10.1.0.1|255.255.255.0 1002|10.1.0.2|255.255.255.0 1003|10.1.0.3|255.255.255.0 1004|10.1.0.4|255.255.255.0 1005|10.1.0.5|255.255.255.0 opengnb-ver1.6.0.a/examples/node_config_example/scripts/000077500000000000000000000000001500454252100233725ustar00rootroot00000000000000opengnb-ver1.6.0.a/examples/node_config_example/scripts/if_down_darwin.sh000077500000000000000000000003171500454252100267230ustar00rootroot00000000000000#!/bin/sh if [ -n "$GNB_IF_NAME" ] ; then echo $GNB_MTU > "/sys/class/net/$GNB_IF_NAME/mtu" fi #if [ -n "$GNB_TUN_IPV6" ] ; then # ip -6 address add "$GNB_TUN_IPV6/96" dev $GNB_IF_NAME #fi opengnb-ver1.6.0.a/examples/node_config_example/scripts/if_down_freebsd.sh000077500000000000000000000001121500454252100270420ustar00rootroot00000000000000#!/bin/sh #GNB ENV $GNB_IF_NAME $GNB_MTU $GNB_TUN_IPV4 $GNB_TUN_IPV6 opengnb-ver1.6.0.a/examples/node_config_example/scripts/if_down_linux.sh000077500000000000000000000001311500454252100265700ustar00rootroot00000000000000#!/bin/sh # if_down_linux.sh #GNB ENV $GNB_IF_NAME $GNB_MTU $GNB_TUN_IPV4 $GNB_TUN_IPV6 opengnb-ver1.6.0.a/examples/node_config_example/scripts/if_down_openbsd.sh000077500000000000000000000001071500454252100270660ustar00rootroot00000000000000#!/bin/sh #GNB ENV $GNB_IF_NAME $GNB_MTU $GNB_TUN_IPV4 $GNB_TUN_IPV6 opengnb-ver1.6.0.a/examples/node_config_example/scripts/if_up_darwin.sh000077500000000000000000000001111500454252100263700ustar00rootroot00000000000000#!/bin/sh #GNB ENV $GNB_IF_NAME $GNB_MTU $GNB_TUN_IPV4 $GNB_TUN_IPV6 opengnb-ver1.6.0.a/examples/node_config_example/scripts/if_up_freebsd.sh000077500000000000000000000001121500454252100265170ustar00rootroot00000000000000#!/bin/sh #GNB ENV $GNB_IF_NAME $GNB_MTU $GNB_TUN_IPV4 $GNB_TUN_IPV6 opengnb-ver1.6.0.a/examples/node_config_example/scripts/if_up_linux.sh000077500000000000000000000001271500454252100262520ustar00rootroot00000000000000#!/bin/sh # if_up_linux.sh #GNB ENV $GNB_IF_NAME $GNB_MTU $GNB_TUN_IPV4 $GNB_TUN_IPV6 opengnb-ver1.6.0.a/examples/node_config_example/scripts/if_up_openbsd.sh000077500000000000000000000001111500454252100265360ustar00rootroot00000000000000#!/bin/sh #GNB ENV $GNB_IF_NAME $GNB_MTU $GNB_TUN_IPV4 $GNB_TUN_IPV6 opengnb-ver1.6.0.a/libs/000077500000000000000000000000001500454252100150315ustar00rootroot00000000000000opengnb-ver1.6.0.a/libs/README.md000066400000000000000000000014531500454252100163130ustar00rootroot00000000000000# OpenGNB [OpenGNB](https://github.com/gnbdev/opengnb "OpenGNB")是一个开源的去中心化的具有极致内网穿透能力的通过P2P进行三层网络交换的虚拟组网系统。 编译链接OpenGNB的源码时不需要安装第三方库文件和头文件,这使得OpenGNB可以轻易在许多操作系统上构建;但必须要明确说明的是,OpenGNB使用了一些第三方源代码,这个目录下存放的正是OpenGNB项目所使用到所有第三方源代码,这些源代码版权归原作者所有。 [ed25519](https://github.com/orlp/ed25519 "ed25519") [miniupnp](https://github.com/miniupnp/miniupnp "miniupnp") [tap-windows6](https://github.com/OpenVPN/tap-windows6 "tap-windows6") [nginx](https://github.com/nginx/nginx "nginx") [zlib](https://www.zlib.net/ "zlib") opengnb-ver1.6.0.a/libs/ed25519/000077500000000000000000000000001500454252100160275ustar00rootroot00000000000000opengnb-ver1.6.0.a/libs/ed25519/add_scalar.c000066400000000000000000000041721500454252100202540ustar00rootroot00000000000000#include "ed25519.h" #include "ge.h" #include "sc.h" #include "sha512.h" /* see http://crypto.stackexchange.com/a/6215/4697 */ void ed25519_add_scalar(unsigned char *public_key, unsigned char *private_key, const unsigned char *scalar) { const unsigned char SC_1[32] = {1}; /* scalar with value 1 */ unsigned char n[32]; ge_p3 nB; ge_p1p1 A_p1p1; ge_p3 A; ge_p3 public_key_unpacked; ge_cached T; sha512_context hash; unsigned char hashbuf[64]; int i; /* copy the scalar and clear highest bit */ for (i = 0; i < 31; ++i) { n[i] = scalar[i]; } n[31] = scalar[31] & 127; /* private key: a = n + t */ if (private_key) { sc_muladd(private_key, SC_1, n, private_key); // https://github.com/orlp/ed25519/issues/3 sha512_init(&hash); sha512_update(&hash, private_key + 32, 32); sha512_update(&hash, scalar, 32); sha512_final(&hash, hashbuf); for (i = 0; i < 32; ++i) { private_key[32 + i] = hashbuf[i]; } } /* public key: A = nB + T */ if (public_key) { /* if we know the private key we don't need a point addition, which is faster */ /* using a "timing attack" you could find out wether or not we know the private key, but this information seems rather useless - if this is important pass public_key and private_key seperately in 2 function calls */ if (private_key) { ge_scalarmult_base(&A, private_key); } else { /* unpack public key into T */ ge_frombytes_negate_vartime(&public_key_unpacked, public_key); fe_neg(public_key_unpacked.X, public_key_unpacked.X); /* undo negate */ fe_neg(public_key_unpacked.T, public_key_unpacked.T); /* undo negate */ ge_p3_to_cached(&T, &public_key_unpacked); /* calculate n*B */ ge_scalarmult_base(&nB, n); /* A = n*B + T */ ge_add(&A_p1p1, &nB, &T); ge_p1p1_to_p3(&A, &A_p1p1); } /* pack public key */ ge_p3_tobytes(public_key, &A); } } opengnb-ver1.6.0.a/libs/ed25519/ed25519.h000066400000000000000000000023431500454252100172000ustar00rootroot00000000000000#ifndef ED25519_H #define ED25519_H #include #if defined(_WIN32) #if defined(ED25519_BUILD_DLL) #define ED25519_DECLSPEC __declspec(dllexport) #elif defined(ED25519_DLL) #define ED25519_DECLSPEC __declspec(dllimport) #else #define ED25519_DECLSPEC #endif #else #define ED25519_DECLSPEC #endif #ifdef __cplusplus extern "C" { #endif #ifndef ED25519_NO_SEED int ED25519_DECLSPEC ed25519_create_seed(unsigned char *seed); #endif void ED25519_DECLSPEC ed25519_create_keypair(unsigned char *public_key, unsigned char *private_key, const unsigned char *seed); void ED25519_DECLSPEC ed25519_sign(unsigned char *signature, const unsigned char *message, size_t message_len, const unsigned char *public_key, const unsigned char *private_key); int ED25519_DECLSPEC ed25519_verify(const unsigned char *signature, const unsigned char *message, size_t message_len, const unsigned char *public_key); void ED25519_DECLSPEC ed25519_add_scalar(unsigned char *public_key, unsigned char *private_key, const unsigned char *scalar); void ED25519_DECLSPEC ed25519_key_exchange(unsigned char *shared_secret, const unsigned char *public_key, const unsigned char *private_key); #ifdef __cplusplus } #endif #endif opengnb-ver1.6.0.a/libs/ed25519/fe.c000066400000000000000000001136731500454252100166000ustar00rootroot00000000000000#include "fixedint.h" #include "fe.h" /* helper functions */ static uint64_t load_3(const unsigned char *in) { uint64_t result; result = (uint64_t) in[0]; result |= ((uint64_t) in[1]) << 8; result |= ((uint64_t) in[2]) << 16; return result; } static uint64_t load_4(const unsigned char *in) { uint64_t result; result = (uint64_t) in[0]; result |= ((uint64_t) in[1]) << 8; result |= ((uint64_t) in[2]) << 16; result |= ((uint64_t) in[3]) << 24; return result; } /* h = 0 */ void fe_0(fe h) { h[0] = 0; h[1] = 0; h[2] = 0; h[3] = 0; h[4] = 0; h[5] = 0; h[6] = 0; h[7] = 0; h[8] = 0; h[9] = 0; } /* h = 1 */ void fe_1(fe h) { h[0] = 1; h[1] = 0; h[2] = 0; h[3] = 0; h[4] = 0; h[5] = 0; h[6] = 0; h[7] = 0; h[8] = 0; h[9] = 0; } /* h = f + g Can overlap h with f or g. Preconditions: |f| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. |g| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. Postconditions: |h| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. */ void fe_add(fe h, const fe f, const fe g) { int32_t f0 = f[0]; int32_t f1 = f[1]; int32_t f2 = f[2]; int32_t f3 = f[3]; int32_t f4 = f[4]; int32_t f5 = f[5]; int32_t f6 = f[6]; int32_t f7 = f[7]; int32_t f8 = f[8]; int32_t f9 = f[9]; int32_t g0 = g[0]; int32_t g1 = g[1]; int32_t g2 = g[2]; int32_t g3 = g[3]; int32_t g4 = g[4]; int32_t g5 = g[5]; int32_t g6 = g[6]; int32_t g7 = g[7]; int32_t g8 = g[8]; int32_t g9 = g[9]; int32_t h0 = f0 + g0; int32_t h1 = f1 + g1; int32_t h2 = f2 + g2; int32_t h3 = f3 + g3; int32_t h4 = f4 + g4; int32_t h5 = f5 + g5; int32_t h6 = f6 + g6; int32_t h7 = f7 + g7; int32_t h8 = f8 + g8; int32_t h9 = f9 + g9; h[0] = h0; h[1] = h1; h[2] = h2; h[3] = h3; h[4] = h4; h[5] = h5; h[6] = h6; h[7] = h7; h[8] = h8; h[9] = h9; } /* Replace (f,g) with (g,g) if b == 1; replace (f,g) with (f,g) if b == 0. Preconditions: b in {0,1}. */ void fe_cmov(fe f, const fe g, unsigned int b) { int32_t f0 = f[0]; int32_t f1 = f[1]; int32_t f2 = f[2]; int32_t f3 = f[3]; int32_t f4 = f[4]; int32_t f5 = f[5]; int32_t f6 = f[6]; int32_t f7 = f[7]; int32_t f8 = f[8]; int32_t f9 = f[9]; int32_t g0 = g[0]; int32_t g1 = g[1]; int32_t g2 = g[2]; int32_t g3 = g[3]; int32_t g4 = g[4]; int32_t g5 = g[5]; int32_t g6 = g[6]; int32_t g7 = g[7]; int32_t g8 = g[8]; int32_t g9 = g[9]; int32_t x0 = f0 ^ g0; int32_t x1 = f1 ^ g1; int32_t x2 = f2 ^ g2; int32_t x3 = f3 ^ g3; int32_t x4 = f4 ^ g4; int32_t x5 = f5 ^ g5; int32_t x6 = f6 ^ g6; int32_t x7 = f7 ^ g7; int32_t x8 = f8 ^ g8; int32_t x9 = f9 ^ g9; b = (unsigned int) (- (int) b); /* silence warning */ x0 &= b; x1 &= b; x2 &= b; x3 &= b; x4 &= b; x5 &= b; x6 &= b; x7 &= b; x8 &= b; x9 &= b; f[0] = f0 ^ x0; f[1] = f1 ^ x1; f[2] = f2 ^ x2; f[3] = f3 ^ x3; f[4] = f4 ^ x4; f[5] = f5 ^ x5; f[6] = f6 ^ x6; f[7] = f7 ^ x7; f[8] = f8 ^ x8; f[9] = f9 ^ x9; } /* Replace (f,g) with (g,f) if b == 1; replace (f,g) with (f,g) if b == 0. Preconditions: b in {0,1}. */ void fe_cswap(fe f,fe g,unsigned int b) { int32_t f0 = f[0]; int32_t f1 = f[1]; int32_t f2 = f[2]; int32_t f3 = f[3]; int32_t f4 = f[4]; int32_t f5 = f[5]; int32_t f6 = f[6]; int32_t f7 = f[7]; int32_t f8 = f[8]; int32_t f9 = f[9]; int32_t g0 = g[0]; int32_t g1 = g[1]; int32_t g2 = g[2]; int32_t g3 = g[3]; int32_t g4 = g[4]; int32_t g5 = g[5]; int32_t g6 = g[6]; int32_t g7 = g[7]; int32_t g8 = g[8]; int32_t g9 = g[9]; int32_t x0 = f0 ^ g0; int32_t x1 = f1 ^ g1; int32_t x2 = f2 ^ g2; int32_t x3 = f3 ^ g3; int32_t x4 = f4 ^ g4; int32_t x5 = f5 ^ g5; int32_t x6 = f6 ^ g6; int32_t x7 = f7 ^ g7; int32_t x8 = f8 ^ g8; int32_t x9 = f9 ^ g9; b = (unsigned int) (- (int) b); /* silence warning */ x0 &= b; x1 &= b; x2 &= b; x3 &= b; x4 &= b; x5 &= b; x6 &= b; x7 &= b; x8 &= b; x9 &= b; f[0] = f0 ^ x0; f[1] = f1 ^ x1; f[2] = f2 ^ x2; f[3] = f3 ^ x3; f[4] = f4 ^ x4; f[5] = f5 ^ x5; f[6] = f6 ^ x6; f[7] = f7 ^ x7; f[8] = f8 ^ x8; f[9] = f9 ^ x9; g[0] = g0 ^ x0; g[1] = g1 ^ x1; g[2] = g2 ^ x2; g[3] = g3 ^ x3; g[4] = g4 ^ x4; g[5] = g5 ^ x5; g[6] = g6 ^ x6; g[7] = g7 ^ x7; g[8] = g8 ^ x8; g[9] = g9 ^ x9; } /* h = f */ void fe_copy(fe h, const fe f) { int32_t f0 = f[0]; int32_t f1 = f[1]; int32_t f2 = f[2]; int32_t f3 = f[3]; int32_t f4 = f[4]; int32_t f5 = f[5]; int32_t f6 = f[6]; int32_t f7 = f[7]; int32_t f8 = f[8]; int32_t f9 = f[9]; h[0] = f0; h[1] = f1; h[2] = f2; h[3] = f3; h[4] = f4; h[5] = f5; h[6] = f6; h[7] = f7; h[8] = f8; h[9] = f9; } /* Ignores top bit of h. */ void fe_frombytes(fe h, const unsigned char *s) { int64_t h0 = load_4(s); int64_t h1 = load_3(s + 4) << 6; int64_t h2 = load_3(s + 7) << 5; int64_t h3 = load_3(s + 10) << 3; int64_t h4 = load_3(s + 13) << 2; int64_t h5 = load_4(s + 16); int64_t h6 = load_3(s + 20) << 7; int64_t h7 = load_3(s + 23) << 5; int64_t h8 = load_3(s + 26) << 4; int64_t h9 = (load_3(s + 29) & 8388607) << 2; int64_t carry0; int64_t carry1; int64_t carry2; int64_t carry3; int64_t carry4; int64_t carry5; int64_t carry6; int64_t carry7; int64_t carry8; int64_t carry9; carry9 = (h9 + (int64_t) (1 << 24)) >> 25; h0 += carry9 * 19; h9 -= carry9 << 25; carry1 = (h1 + (int64_t) (1 << 24)) >> 25; h2 += carry1; h1 -= carry1 << 25; carry3 = (h3 + (int64_t) (1 << 24)) >> 25; h4 += carry3; h3 -= carry3 << 25; carry5 = (h5 + (int64_t) (1 << 24)) >> 25; h6 += carry5; h5 -= carry5 << 25; carry7 = (h7 + (int64_t) (1 << 24)) >> 25; h8 += carry7; h7 -= carry7 << 25; carry0 = (h0 + (int64_t) (1 << 25)) >> 26; h1 += carry0; h0 -= carry0 << 26; carry2 = (h2 + (int64_t) (1 << 25)) >> 26; h3 += carry2; h2 -= carry2 << 26; carry4 = (h4 + (int64_t) (1 << 25)) >> 26; h5 += carry4; h4 -= carry4 << 26; carry6 = (h6 + (int64_t) (1 << 25)) >> 26; h7 += carry6; h6 -= carry6 << 26; carry8 = (h8 + (int64_t) (1 << 25)) >> 26; h9 += carry8; h8 -= carry8 << 26; h[0] = (int32_t) h0; h[1] = (int32_t) h1; h[2] = (int32_t) h2; h[3] = (int32_t) h3; h[4] = (int32_t) h4; h[5] = (int32_t) h5; h[6] = (int32_t) h6; h[7] = (int32_t) h7; h[8] = (int32_t) h8; h[9] = (int32_t) h9; } void fe_invert(fe out, const fe z) { fe t0; fe t1; fe t2; fe t3; int i; fe_sq(t0, z); for (i = 1; i < 1; ++i) { fe_sq(t0, t0); } fe_sq(t1, t0); for (i = 1; i < 2; ++i) { fe_sq(t1, t1); } fe_mul(t1, z, t1); fe_mul(t0, t0, t1); fe_sq(t2, t0); for (i = 1; i < 1; ++i) { fe_sq(t2, t2); } fe_mul(t1, t1, t2); fe_sq(t2, t1); for (i = 1; i < 5; ++i) { fe_sq(t2, t2); } fe_mul(t1, t2, t1); fe_sq(t2, t1); for (i = 1; i < 10; ++i) { fe_sq(t2, t2); } fe_mul(t2, t2, t1); fe_sq(t3, t2); for (i = 1; i < 20; ++i) { fe_sq(t3, t3); } fe_mul(t2, t3, t2); fe_sq(t2, t2); for (i = 1; i < 10; ++i) { fe_sq(t2, t2); } fe_mul(t1, t2, t1); fe_sq(t2, t1); for (i = 1; i < 50; ++i) { fe_sq(t2, t2); } fe_mul(t2, t2, t1); fe_sq(t3, t2); for (i = 1; i < 100; ++i) { fe_sq(t3, t3); } fe_mul(t2, t3, t2); fe_sq(t2, t2); for (i = 1; i < 50; ++i) { fe_sq(t2, t2); } fe_mul(t1, t2, t1); fe_sq(t1, t1); for (i = 1; i < 5; ++i) { fe_sq(t1, t1); } fe_mul(out, t1, t0); } /* return 1 if f is in {1,3,5,...,q-2} return 0 if f is in {0,2,4,...,q-1} Preconditions: |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. */ int fe_isnegative(const fe f) { unsigned char s[32]; fe_tobytes(s, f); return s[0] & 1; } /* return 1 if f == 0 return 0 if f != 0 Preconditions: |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. */ int fe_isnonzero(const fe f) { unsigned char s[32]; unsigned char r; fe_tobytes(s, f); r = s[0]; #define F(i) r |= s[i] F(1); F(2); F(3); F(4); F(5); F(6); F(7); F(8); F(9); F(10); F(11); F(12); F(13); F(14); F(15); F(16); F(17); F(18); F(19); F(20); F(21); F(22); F(23); F(24); F(25); F(26); F(27); F(28); F(29); F(30); F(31); #undef F return r != 0; } /* h = f * g Can overlap h with f or g. Preconditions: |f| bounded by 1.65*2^26,1.65*2^25,1.65*2^26,1.65*2^25,etc. |g| bounded by 1.65*2^26,1.65*2^25,1.65*2^26,1.65*2^25,etc. Postconditions: |h| bounded by 1.01*2^25,1.01*2^24,1.01*2^25,1.01*2^24,etc. */ /* Notes on implementation strategy: Using schoolbook multiplication. Karatsuba would save a little in some cost models. Most multiplications by 2 and 19 are 32-bit precomputations; cheaper than 64-bit postcomputations. There is one remaining multiplication by 19 in the carry chain; one *19 precomputation can be merged into this, but the resulting data flow is considerably less clean. There are 12 carries below. 10 of them are 2-way parallelizable and vectorizable. Can get away with 11 carries, but then data flow is much deeper. With tighter constraints on inputs can squeeze carries into int32. */ void fe_mul(fe h, const fe f, const fe g) { int32_t f0 = f[0]; int32_t f1 = f[1]; int32_t f2 = f[2]; int32_t f3 = f[3]; int32_t f4 = f[4]; int32_t f5 = f[5]; int32_t f6 = f[6]; int32_t f7 = f[7]; int32_t f8 = f[8]; int32_t f9 = f[9]; int32_t g0 = g[0]; int32_t g1 = g[1]; int32_t g2 = g[2]; int32_t g3 = g[3]; int32_t g4 = g[4]; int32_t g5 = g[5]; int32_t g6 = g[6]; int32_t g7 = g[7]; int32_t g8 = g[8]; int32_t g9 = g[9]; int32_t g1_19 = 19 * g1; /* 1.959375*2^29 */ int32_t g2_19 = 19 * g2; /* 1.959375*2^30; still ok */ int32_t g3_19 = 19 * g3; int32_t g4_19 = 19 * g4; int32_t g5_19 = 19 * g5; int32_t g6_19 = 19 * g6; int32_t g7_19 = 19 * g7; int32_t g8_19 = 19 * g8; int32_t g9_19 = 19 * g9; int32_t f1_2 = 2 * f1; int32_t f3_2 = 2 * f3; int32_t f5_2 = 2 * f5; int32_t f7_2 = 2 * f7; int32_t f9_2 = 2 * f9; int64_t f0g0 = f0 * (int64_t) g0; int64_t f0g1 = f0 * (int64_t) g1; int64_t f0g2 = f0 * (int64_t) g2; int64_t f0g3 = f0 * (int64_t) g3; int64_t f0g4 = f0 * (int64_t) g4; int64_t f0g5 = f0 * (int64_t) g5; int64_t f0g6 = f0 * (int64_t) g6; int64_t f0g7 = f0 * (int64_t) g7; int64_t f0g8 = f0 * (int64_t) g8; int64_t f0g9 = f0 * (int64_t) g9; int64_t f1g0 = f1 * (int64_t) g0; int64_t f1g1_2 = f1_2 * (int64_t) g1; int64_t f1g2 = f1 * (int64_t) g2; int64_t f1g3_2 = f1_2 * (int64_t) g3; int64_t f1g4 = f1 * (int64_t) g4; int64_t f1g5_2 = f1_2 * (int64_t) g5; int64_t f1g6 = f1 * (int64_t) g6; int64_t f1g7_2 = f1_2 * (int64_t) g7; int64_t f1g8 = f1 * (int64_t) g8; int64_t f1g9_38 = f1_2 * (int64_t) g9_19; int64_t f2g0 = f2 * (int64_t) g0; int64_t f2g1 = f2 * (int64_t) g1; int64_t f2g2 = f2 * (int64_t) g2; int64_t f2g3 = f2 * (int64_t) g3; int64_t f2g4 = f2 * (int64_t) g4; int64_t f2g5 = f2 * (int64_t) g5; int64_t f2g6 = f2 * (int64_t) g6; int64_t f2g7 = f2 * (int64_t) g7; int64_t f2g8_19 = f2 * (int64_t) g8_19; int64_t f2g9_19 = f2 * (int64_t) g9_19; int64_t f3g0 = f3 * (int64_t) g0; int64_t f3g1_2 = f3_2 * (int64_t) g1; int64_t f3g2 = f3 * (int64_t) g2; int64_t f3g3_2 = f3_2 * (int64_t) g3; int64_t f3g4 = f3 * (int64_t) g4; int64_t f3g5_2 = f3_2 * (int64_t) g5; int64_t f3g6 = f3 * (int64_t) g6; int64_t f3g7_38 = f3_2 * (int64_t) g7_19; int64_t f3g8_19 = f3 * (int64_t) g8_19; int64_t f3g9_38 = f3_2 * (int64_t) g9_19; int64_t f4g0 = f4 * (int64_t) g0; int64_t f4g1 = f4 * (int64_t) g1; int64_t f4g2 = f4 * (int64_t) g2; int64_t f4g3 = f4 * (int64_t) g3; int64_t f4g4 = f4 * (int64_t) g4; int64_t f4g5 = f4 * (int64_t) g5; int64_t f4g6_19 = f4 * (int64_t) g6_19; int64_t f4g7_19 = f4 * (int64_t) g7_19; int64_t f4g8_19 = f4 * (int64_t) g8_19; int64_t f4g9_19 = f4 * (int64_t) g9_19; int64_t f5g0 = f5 * (int64_t) g0; int64_t f5g1_2 = f5_2 * (int64_t) g1; int64_t f5g2 = f5 * (int64_t) g2; int64_t f5g3_2 = f5_2 * (int64_t) g3; int64_t f5g4 = f5 * (int64_t) g4; int64_t f5g5_38 = f5_2 * (int64_t) g5_19; int64_t f5g6_19 = f5 * (int64_t) g6_19; int64_t f5g7_38 = f5_2 * (int64_t) g7_19; int64_t f5g8_19 = f5 * (int64_t) g8_19; int64_t f5g9_38 = f5_2 * (int64_t) g9_19; int64_t f6g0 = f6 * (int64_t) g0; int64_t f6g1 = f6 * (int64_t) g1; int64_t f6g2 = f6 * (int64_t) g2; int64_t f6g3 = f6 * (int64_t) g3; int64_t f6g4_19 = f6 * (int64_t) g4_19; int64_t f6g5_19 = f6 * (int64_t) g5_19; int64_t f6g6_19 = f6 * (int64_t) g6_19; int64_t f6g7_19 = f6 * (int64_t) g7_19; int64_t f6g8_19 = f6 * (int64_t) g8_19; int64_t f6g9_19 = f6 * (int64_t) g9_19; int64_t f7g0 = f7 * (int64_t) g0; int64_t f7g1_2 = f7_2 * (int64_t) g1; int64_t f7g2 = f7 * (int64_t) g2; int64_t f7g3_38 = f7_2 * (int64_t) g3_19; int64_t f7g4_19 = f7 * (int64_t) g4_19; int64_t f7g5_38 = f7_2 * (int64_t) g5_19; int64_t f7g6_19 = f7 * (int64_t) g6_19; int64_t f7g7_38 = f7_2 * (int64_t) g7_19; int64_t f7g8_19 = f7 * (int64_t) g8_19; int64_t f7g9_38 = f7_2 * (int64_t) g9_19; int64_t f8g0 = f8 * (int64_t) g0; int64_t f8g1 = f8 * (int64_t) g1; int64_t f8g2_19 = f8 * (int64_t) g2_19; int64_t f8g3_19 = f8 * (int64_t) g3_19; int64_t f8g4_19 = f8 * (int64_t) g4_19; int64_t f8g5_19 = f8 * (int64_t) g5_19; int64_t f8g6_19 = f8 * (int64_t) g6_19; int64_t f8g7_19 = f8 * (int64_t) g7_19; int64_t f8g8_19 = f8 * (int64_t) g8_19; int64_t f8g9_19 = f8 * (int64_t) g9_19; int64_t f9g0 = f9 * (int64_t) g0; int64_t f9g1_38 = f9_2 * (int64_t) g1_19; int64_t f9g2_19 = f9 * (int64_t) g2_19; int64_t f9g3_38 = f9_2 * (int64_t) g3_19; int64_t f9g4_19 = f9 * (int64_t) g4_19; int64_t f9g5_38 = f9_2 * (int64_t) g5_19; int64_t f9g6_19 = f9 * (int64_t) g6_19; int64_t f9g7_38 = f9_2 * (int64_t) g7_19; int64_t f9g8_19 = f9 * (int64_t) g8_19; int64_t f9g9_38 = f9_2 * (int64_t) g9_19; int64_t h0 = f0g0 + f1g9_38 + f2g8_19 + f3g7_38 + f4g6_19 + f5g5_38 + f6g4_19 + f7g3_38 + f8g2_19 + f9g1_38; int64_t h1 = f0g1 + f1g0 + f2g9_19 + f3g8_19 + f4g7_19 + f5g6_19 + f6g5_19 + f7g4_19 + f8g3_19 + f9g2_19; int64_t h2 = f0g2 + f1g1_2 + f2g0 + f3g9_38 + f4g8_19 + f5g7_38 + f6g6_19 + f7g5_38 + f8g4_19 + f9g3_38; int64_t h3 = f0g3 + f1g2 + f2g1 + f3g0 + f4g9_19 + f5g8_19 + f6g7_19 + f7g6_19 + f8g5_19 + f9g4_19; int64_t h4 = f0g4 + f1g3_2 + f2g2 + f3g1_2 + f4g0 + f5g9_38 + f6g8_19 + f7g7_38 + f8g6_19 + f9g5_38; int64_t h5 = f0g5 + f1g4 + f2g3 + f3g2 + f4g1 + f5g0 + f6g9_19 + f7g8_19 + f8g7_19 + f9g6_19; int64_t h6 = f0g6 + f1g5_2 + f2g4 + f3g3_2 + f4g2 + f5g1_2 + f6g0 + f7g9_38 + f8g8_19 + f9g7_38; int64_t h7 = f0g7 + f1g6 + f2g5 + f3g4 + f4g3 + f5g2 + f6g1 + f7g0 + f8g9_19 + f9g8_19; int64_t h8 = f0g8 + f1g7_2 + f2g6 + f3g5_2 + f4g4 + f5g3_2 + f6g2 + f7g1_2 + f8g0 + f9g9_38; int64_t h9 = f0g9 + f1g8 + f2g7 + f3g6 + f4g5 + f5g4 + f6g3 + f7g2 + f8g1 + f9g0 ; int64_t carry0; int64_t carry1; int64_t carry2; int64_t carry3; int64_t carry4; int64_t carry5; int64_t carry6; int64_t carry7; int64_t carry8; int64_t carry9; carry0 = (h0 + (int64_t) (1 << 25)) >> 26; h1 += carry0; h0 -= carry0 << 26; carry4 = (h4 + (int64_t) (1 << 25)) >> 26; h5 += carry4; h4 -= carry4 << 26; carry1 = (h1 + (int64_t) (1 << 24)) >> 25; h2 += carry1; h1 -= carry1 << 25; carry5 = (h5 + (int64_t) (1 << 24)) >> 25; h6 += carry5; h5 -= carry5 << 25; carry2 = (h2 + (int64_t) (1 << 25)) >> 26; h3 += carry2; h2 -= carry2 << 26; carry6 = (h6 + (int64_t) (1 << 25)) >> 26; h7 += carry6; h6 -= carry6 << 26; carry3 = (h3 + (int64_t) (1 << 24)) >> 25; h4 += carry3; h3 -= carry3 << 25; carry7 = (h7 + (int64_t) (1 << 24)) >> 25; h8 += carry7; h7 -= carry7 << 25; carry4 = (h4 + (int64_t) (1 << 25)) >> 26; h5 += carry4; h4 -= carry4 << 26; carry8 = (h8 + (int64_t) (1 << 25)) >> 26; h9 += carry8; h8 -= carry8 << 26; carry9 = (h9 + (int64_t) (1 << 24)) >> 25; h0 += carry9 * 19; h9 -= carry9 << 25; carry0 = (h0 + (int64_t) (1 << 25)) >> 26; h1 += carry0; h0 -= carry0 << 26; h[0] = (int32_t) h0; h[1] = (int32_t) h1; h[2] = (int32_t) h2; h[3] = (int32_t) h3; h[4] = (int32_t) h4; h[5] = (int32_t) h5; h[6] = (int32_t) h6; h[7] = (int32_t) h7; h[8] = (int32_t) h8; h[9] = (int32_t) h9; } /* h = f * 121666 Can overlap h with f. Preconditions: |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. Postconditions: |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. */ void fe_mul121666(fe h, fe f) { int32_t f0 = f[0]; int32_t f1 = f[1]; int32_t f2 = f[2]; int32_t f3 = f[3]; int32_t f4 = f[4]; int32_t f5 = f[5]; int32_t f6 = f[6]; int32_t f7 = f[7]; int32_t f8 = f[8]; int32_t f9 = f[9]; int64_t h0 = f0 * (int64_t) 121666; int64_t h1 = f1 * (int64_t) 121666; int64_t h2 = f2 * (int64_t) 121666; int64_t h3 = f3 * (int64_t) 121666; int64_t h4 = f4 * (int64_t) 121666; int64_t h5 = f5 * (int64_t) 121666; int64_t h6 = f6 * (int64_t) 121666; int64_t h7 = f7 * (int64_t) 121666; int64_t h8 = f8 * (int64_t) 121666; int64_t h9 = f9 * (int64_t) 121666; int64_t carry0; int64_t carry1; int64_t carry2; int64_t carry3; int64_t carry4; int64_t carry5; int64_t carry6; int64_t carry7; int64_t carry8; int64_t carry9; carry9 = (h9 + (int64_t) (1<<24)) >> 25; h0 += carry9 * 19; h9 -= carry9 << 25; carry1 = (h1 + (int64_t) (1<<24)) >> 25; h2 += carry1; h1 -= carry1 << 25; carry3 = (h3 + (int64_t) (1<<24)) >> 25; h4 += carry3; h3 -= carry3 << 25; carry5 = (h5 + (int64_t) (1<<24)) >> 25; h6 += carry5; h5 -= carry5 << 25; carry7 = (h7 + (int64_t) (1<<24)) >> 25; h8 += carry7; h7 -= carry7 << 25; carry0 = (h0 + (int64_t) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26; carry2 = (h2 + (int64_t) (1<<25)) >> 26; h3 += carry2; h2 -= carry2 << 26; carry4 = (h4 + (int64_t) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26; carry6 = (h6 + (int64_t) (1<<25)) >> 26; h7 += carry6; h6 -= carry6 << 26; carry8 = (h8 + (int64_t) (1<<25)) >> 26; h9 += carry8; h8 -= carry8 << 26; h[0] = (int32_t) h0; h[1] = (int32_t) h1; h[2] = (int32_t) h2; h[3] = (int32_t) h3; h[4] = (int32_t) h4; h[5] = (int32_t) h5; h[6] = (int32_t) h6; h[7] = (int32_t) h7; h[8] = (int32_t) h8; h[9] = (int32_t) h9; } /* h = -f Preconditions: |f| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. Postconditions: |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. */ void fe_neg(fe h, const fe f) { int32_t f0 = f[0]; int32_t f1 = f[1]; int32_t f2 = f[2]; int32_t f3 = f[3]; int32_t f4 = f[4]; int32_t f5 = f[5]; int32_t f6 = f[6]; int32_t f7 = f[7]; int32_t f8 = f[8]; int32_t f9 = f[9]; int32_t h0 = -f0; int32_t h1 = -f1; int32_t h2 = -f2; int32_t h3 = -f3; int32_t h4 = -f4; int32_t h5 = -f5; int32_t h6 = -f6; int32_t h7 = -f7; int32_t h8 = -f8; int32_t h9 = -f9; h[0] = h0; h[1] = h1; h[2] = h2; h[3] = h3; h[4] = h4; h[5] = h5; h[6] = h6; h[7] = h7; h[8] = h8; h[9] = h9; } void fe_pow22523(fe out, const fe z) { fe t0; fe t1; fe t2; int i; fe_sq(t0, z); for (i = 1; i < 1; ++i) { fe_sq(t0, t0); } fe_sq(t1, t0); for (i = 1; i < 2; ++i) { fe_sq(t1, t1); } fe_mul(t1, z, t1); fe_mul(t0, t0, t1); fe_sq(t0, t0); for (i = 1; i < 1; ++i) { fe_sq(t0, t0); } fe_mul(t0, t1, t0); fe_sq(t1, t0); for (i = 1; i < 5; ++i) { fe_sq(t1, t1); } fe_mul(t0, t1, t0); fe_sq(t1, t0); for (i = 1; i < 10; ++i) { fe_sq(t1, t1); } fe_mul(t1, t1, t0); fe_sq(t2, t1); for (i = 1; i < 20; ++i) { fe_sq(t2, t2); } fe_mul(t1, t2, t1); fe_sq(t1, t1); for (i = 1; i < 10; ++i) { fe_sq(t1, t1); } fe_mul(t0, t1, t0); fe_sq(t1, t0); for (i = 1; i < 50; ++i) { fe_sq(t1, t1); } fe_mul(t1, t1, t0); fe_sq(t2, t1); for (i = 1; i < 100; ++i) { fe_sq(t2, t2); } fe_mul(t1, t2, t1); fe_sq(t1, t1); for (i = 1; i < 50; ++i) { fe_sq(t1, t1); } fe_mul(t0, t1, t0); fe_sq(t0, t0); for (i = 1; i < 2; ++i) { fe_sq(t0, t0); } fe_mul(out, t0, z); return; } /* h = f * f Can overlap h with f. Preconditions: |f| bounded by 1.65*2^26,1.65*2^25,1.65*2^26,1.65*2^25,etc. Postconditions: |h| bounded by 1.01*2^25,1.01*2^24,1.01*2^25,1.01*2^24,etc. */ /* See fe_mul.c for discussion of implementation strategy. */ void fe_sq(fe h, const fe f) { int32_t f0 = f[0]; int32_t f1 = f[1]; int32_t f2 = f[2]; int32_t f3 = f[3]; int32_t f4 = f[4]; int32_t f5 = f[5]; int32_t f6 = f[6]; int32_t f7 = f[7]; int32_t f8 = f[8]; int32_t f9 = f[9]; int32_t f0_2 = 2 * f0; int32_t f1_2 = 2 * f1; int32_t f2_2 = 2 * f2; int32_t f3_2 = 2 * f3; int32_t f4_2 = 2 * f4; int32_t f5_2 = 2 * f5; int32_t f6_2 = 2 * f6; int32_t f7_2 = 2 * f7; int32_t f5_38 = 38 * f5; /* 1.959375*2^30 */ int32_t f6_19 = 19 * f6; /* 1.959375*2^30 */ int32_t f7_38 = 38 * f7; /* 1.959375*2^30 */ int32_t f8_19 = 19 * f8; /* 1.959375*2^30 */ int32_t f9_38 = 38 * f9; /* 1.959375*2^30 */ int64_t f0f0 = f0 * (int64_t) f0; int64_t f0f1_2 = f0_2 * (int64_t) f1; int64_t f0f2_2 = f0_2 * (int64_t) f2; int64_t f0f3_2 = f0_2 * (int64_t) f3; int64_t f0f4_2 = f0_2 * (int64_t) f4; int64_t f0f5_2 = f0_2 * (int64_t) f5; int64_t f0f6_2 = f0_2 * (int64_t) f6; int64_t f0f7_2 = f0_2 * (int64_t) f7; int64_t f0f8_2 = f0_2 * (int64_t) f8; int64_t f0f9_2 = f0_2 * (int64_t) f9; int64_t f1f1_2 = f1_2 * (int64_t) f1; int64_t f1f2_2 = f1_2 * (int64_t) f2; int64_t f1f3_4 = f1_2 * (int64_t) f3_2; int64_t f1f4_2 = f1_2 * (int64_t) f4; int64_t f1f5_4 = f1_2 * (int64_t) f5_2; int64_t f1f6_2 = f1_2 * (int64_t) f6; int64_t f1f7_4 = f1_2 * (int64_t) f7_2; int64_t f1f8_2 = f1_2 * (int64_t) f8; int64_t f1f9_76 = f1_2 * (int64_t) f9_38; int64_t f2f2 = f2 * (int64_t) f2; int64_t f2f3_2 = f2_2 * (int64_t) f3; int64_t f2f4_2 = f2_2 * (int64_t) f4; int64_t f2f5_2 = f2_2 * (int64_t) f5; int64_t f2f6_2 = f2_2 * (int64_t) f6; int64_t f2f7_2 = f2_2 * (int64_t) f7; int64_t f2f8_38 = f2_2 * (int64_t) f8_19; int64_t f2f9_38 = f2 * (int64_t) f9_38; int64_t f3f3_2 = f3_2 * (int64_t) f3; int64_t f3f4_2 = f3_2 * (int64_t) f4; int64_t f3f5_4 = f3_2 * (int64_t) f5_2; int64_t f3f6_2 = f3_2 * (int64_t) f6; int64_t f3f7_76 = f3_2 * (int64_t) f7_38; int64_t f3f8_38 = f3_2 * (int64_t) f8_19; int64_t f3f9_76 = f3_2 * (int64_t) f9_38; int64_t f4f4 = f4 * (int64_t) f4; int64_t f4f5_2 = f4_2 * (int64_t) f5; int64_t f4f6_38 = f4_2 * (int64_t) f6_19; int64_t f4f7_38 = f4 * (int64_t) f7_38; int64_t f4f8_38 = f4_2 * (int64_t) f8_19; int64_t f4f9_38 = f4 * (int64_t) f9_38; int64_t f5f5_38 = f5 * (int64_t) f5_38; int64_t f5f6_38 = f5_2 * (int64_t) f6_19; int64_t f5f7_76 = f5_2 * (int64_t) f7_38; int64_t f5f8_38 = f5_2 * (int64_t) f8_19; int64_t f5f9_76 = f5_2 * (int64_t) f9_38; int64_t f6f6_19 = f6 * (int64_t) f6_19; int64_t f6f7_38 = f6 * (int64_t) f7_38; int64_t f6f8_38 = f6_2 * (int64_t) f8_19; int64_t f6f9_38 = f6 * (int64_t) f9_38; int64_t f7f7_38 = f7 * (int64_t) f7_38; int64_t f7f8_38 = f7_2 * (int64_t) f8_19; int64_t f7f9_76 = f7_2 * (int64_t) f9_38; int64_t f8f8_19 = f8 * (int64_t) f8_19; int64_t f8f9_38 = f8 * (int64_t) f9_38; int64_t f9f9_38 = f9 * (int64_t) f9_38; int64_t h0 = f0f0 + f1f9_76 + f2f8_38 + f3f7_76 + f4f6_38 + f5f5_38; int64_t h1 = f0f1_2 + f2f9_38 + f3f8_38 + f4f7_38 + f5f6_38; int64_t h2 = f0f2_2 + f1f1_2 + f3f9_76 + f4f8_38 + f5f7_76 + f6f6_19; int64_t h3 = f0f3_2 + f1f2_2 + f4f9_38 + f5f8_38 + f6f7_38; int64_t h4 = f0f4_2 + f1f3_4 + f2f2 + f5f9_76 + f6f8_38 + f7f7_38; int64_t h5 = f0f5_2 + f1f4_2 + f2f3_2 + f6f9_38 + f7f8_38; int64_t h6 = f0f6_2 + f1f5_4 + f2f4_2 + f3f3_2 + f7f9_76 + f8f8_19; int64_t h7 = f0f7_2 + f1f6_2 + f2f5_2 + f3f4_2 + f8f9_38; int64_t h8 = f0f8_2 + f1f7_4 + f2f6_2 + f3f5_4 + f4f4 + f9f9_38; int64_t h9 = f0f9_2 + f1f8_2 + f2f7_2 + f3f6_2 + f4f5_2; int64_t carry0; int64_t carry1; int64_t carry2; int64_t carry3; int64_t carry4; int64_t carry5; int64_t carry6; int64_t carry7; int64_t carry8; int64_t carry9; carry0 = (h0 + (int64_t) (1 << 25)) >> 26; h1 += carry0; h0 -= carry0 << 26; carry4 = (h4 + (int64_t) (1 << 25)) >> 26; h5 += carry4; h4 -= carry4 << 26; carry1 = (h1 + (int64_t) (1 << 24)) >> 25; h2 += carry1; h1 -= carry1 << 25; carry5 = (h5 + (int64_t) (1 << 24)) >> 25; h6 += carry5; h5 -= carry5 << 25; carry2 = (h2 + (int64_t) (1 << 25)) >> 26; h3 += carry2; h2 -= carry2 << 26; carry6 = (h6 + (int64_t) (1 << 25)) >> 26; h7 += carry6; h6 -= carry6 << 26; carry3 = (h3 + (int64_t) (1 << 24)) >> 25; h4 += carry3; h3 -= carry3 << 25; carry7 = (h7 + (int64_t) (1 << 24)) >> 25; h8 += carry7; h7 -= carry7 << 25; carry4 = (h4 + (int64_t) (1 << 25)) >> 26; h5 += carry4; h4 -= carry4 << 26; carry8 = (h8 + (int64_t) (1 << 25)) >> 26; h9 += carry8; h8 -= carry8 << 26; carry9 = (h9 + (int64_t) (1 << 24)) >> 25; h0 += carry9 * 19; h9 -= carry9 << 25; carry0 = (h0 + (int64_t) (1 << 25)) >> 26; h1 += carry0; h0 -= carry0 << 26; h[0] = (int32_t) h0; h[1] = (int32_t) h1; h[2] = (int32_t) h2; h[3] = (int32_t) h3; h[4] = (int32_t) h4; h[5] = (int32_t) h5; h[6] = (int32_t) h6; h[7] = (int32_t) h7; h[8] = (int32_t) h8; h[9] = (int32_t) h9; } /* h = 2 * f * f Can overlap h with f. Preconditions: |f| bounded by 1.65*2^26,1.65*2^25,1.65*2^26,1.65*2^25,etc. Postconditions: |h| bounded by 1.01*2^25,1.01*2^24,1.01*2^25,1.01*2^24,etc. */ /* See fe_mul.c for discussion of implementation strategy. */ void fe_sq2(fe h, const fe f) { int32_t f0 = f[0]; int32_t f1 = f[1]; int32_t f2 = f[2]; int32_t f3 = f[3]; int32_t f4 = f[4]; int32_t f5 = f[5]; int32_t f6 = f[6]; int32_t f7 = f[7]; int32_t f8 = f[8]; int32_t f9 = f[9]; int32_t f0_2 = 2 * f0; int32_t f1_2 = 2 * f1; int32_t f2_2 = 2 * f2; int32_t f3_2 = 2 * f3; int32_t f4_2 = 2 * f4; int32_t f5_2 = 2 * f5; int32_t f6_2 = 2 * f6; int32_t f7_2 = 2 * f7; int32_t f5_38 = 38 * f5; /* 1.959375*2^30 */ int32_t f6_19 = 19 * f6; /* 1.959375*2^30 */ int32_t f7_38 = 38 * f7; /* 1.959375*2^30 */ int32_t f8_19 = 19 * f8; /* 1.959375*2^30 */ int32_t f9_38 = 38 * f9; /* 1.959375*2^30 */ int64_t f0f0 = f0 * (int64_t) f0; int64_t f0f1_2 = f0_2 * (int64_t) f1; int64_t f0f2_2 = f0_2 * (int64_t) f2; int64_t f0f3_2 = f0_2 * (int64_t) f3; int64_t f0f4_2 = f0_2 * (int64_t) f4; int64_t f0f5_2 = f0_2 * (int64_t) f5; int64_t f0f6_2 = f0_2 * (int64_t) f6; int64_t f0f7_2 = f0_2 * (int64_t) f7; int64_t f0f8_2 = f0_2 * (int64_t) f8; int64_t f0f9_2 = f0_2 * (int64_t) f9; int64_t f1f1_2 = f1_2 * (int64_t) f1; int64_t f1f2_2 = f1_2 * (int64_t) f2; int64_t f1f3_4 = f1_2 * (int64_t) f3_2; int64_t f1f4_2 = f1_2 * (int64_t) f4; int64_t f1f5_4 = f1_2 * (int64_t) f5_2; int64_t f1f6_2 = f1_2 * (int64_t) f6; int64_t f1f7_4 = f1_2 * (int64_t) f7_2; int64_t f1f8_2 = f1_2 * (int64_t) f8; int64_t f1f9_76 = f1_2 * (int64_t) f9_38; int64_t f2f2 = f2 * (int64_t) f2; int64_t f2f3_2 = f2_2 * (int64_t) f3; int64_t f2f4_2 = f2_2 * (int64_t) f4; int64_t f2f5_2 = f2_2 * (int64_t) f5; int64_t f2f6_2 = f2_2 * (int64_t) f6; int64_t f2f7_2 = f2_2 * (int64_t) f7; int64_t f2f8_38 = f2_2 * (int64_t) f8_19; int64_t f2f9_38 = f2 * (int64_t) f9_38; int64_t f3f3_2 = f3_2 * (int64_t) f3; int64_t f3f4_2 = f3_2 * (int64_t) f4; int64_t f3f5_4 = f3_2 * (int64_t) f5_2; int64_t f3f6_2 = f3_2 * (int64_t) f6; int64_t f3f7_76 = f3_2 * (int64_t) f7_38; int64_t f3f8_38 = f3_2 * (int64_t) f8_19; int64_t f3f9_76 = f3_2 * (int64_t) f9_38; int64_t f4f4 = f4 * (int64_t) f4; int64_t f4f5_2 = f4_2 * (int64_t) f5; int64_t f4f6_38 = f4_2 * (int64_t) f6_19; int64_t f4f7_38 = f4 * (int64_t) f7_38; int64_t f4f8_38 = f4_2 * (int64_t) f8_19; int64_t f4f9_38 = f4 * (int64_t) f9_38; int64_t f5f5_38 = f5 * (int64_t) f5_38; int64_t f5f6_38 = f5_2 * (int64_t) f6_19; int64_t f5f7_76 = f5_2 * (int64_t) f7_38; int64_t f5f8_38 = f5_2 * (int64_t) f8_19; int64_t f5f9_76 = f5_2 * (int64_t) f9_38; int64_t f6f6_19 = f6 * (int64_t) f6_19; int64_t f6f7_38 = f6 * (int64_t) f7_38; int64_t f6f8_38 = f6_2 * (int64_t) f8_19; int64_t f6f9_38 = f6 * (int64_t) f9_38; int64_t f7f7_38 = f7 * (int64_t) f7_38; int64_t f7f8_38 = f7_2 * (int64_t) f8_19; int64_t f7f9_76 = f7_2 * (int64_t) f9_38; int64_t f8f8_19 = f8 * (int64_t) f8_19; int64_t f8f9_38 = f8 * (int64_t) f9_38; int64_t f9f9_38 = f9 * (int64_t) f9_38; int64_t h0 = f0f0 + f1f9_76 + f2f8_38 + f3f7_76 + f4f6_38 + f5f5_38; int64_t h1 = f0f1_2 + f2f9_38 + f3f8_38 + f4f7_38 + f5f6_38; int64_t h2 = f0f2_2 + f1f1_2 + f3f9_76 + f4f8_38 + f5f7_76 + f6f6_19; int64_t h3 = f0f3_2 + f1f2_2 + f4f9_38 + f5f8_38 + f6f7_38; int64_t h4 = f0f4_2 + f1f3_4 + f2f2 + f5f9_76 + f6f8_38 + f7f7_38; int64_t h5 = f0f5_2 + f1f4_2 + f2f3_2 + f6f9_38 + f7f8_38; int64_t h6 = f0f6_2 + f1f5_4 + f2f4_2 + f3f3_2 + f7f9_76 + f8f8_19; int64_t h7 = f0f7_2 + f1f6_2 + f2f5_2 + f3f4_2 + f8f9_38; int64_t h8 = f0f8_2 + f1f7_4 + f2f6_2 + f3f5_4 + f4f4 + f9f9_38; int64_t h9 = f0f9_2 + f1f8_2 + f2f7_2 + f3f6_2 + f4f5_2; int64_t carry0; int64_t carry1; int64_t carry2; int64_t carry3; int64_t carry4; int64_t carry5; int64_t carry6; int64_t carry7; int64_t carry8; int64_t carry9; h0 += h0; h1 += h1; h2 += h2; h3 += h3; h4 += h4; h5 += h5; h6 += h6; h7 += h7; h8 += h8; h9 += h9; carry0 = (h0 + (int64_t) (1 << 25)) >> 26; h1 += carry0; h0 -= carry0 << 26; carry4 = (h4 + (int64_t) (1 << 25)) >> 26; h5 += carry4; h4 -= carry4 << 26; carry1 = (h1 + (int64_t) (1 << 24)) >> 25; h2 += carry1; h1 -= carry1 << 25; carry5 = (h5 + (int64_t) (1 << 24)) >> 25; h6 += carry5; h5 -= carry5 << 25; carry2 = (h2 + (int64_t) (1 << 25)) >> 26; h3 += carry2; h2 -= carry2 << 26; carry6 = (h6 + (int64_t) (1 << 25)) >> 26; h7 += carry6; h6 -= carry6 << 26; carry3 = (h3 + (int64_t) (1 << 24)) >> 25; h4 += carry3; h3 -= carry3 << 25; carry7 = (h7 + (int64_t) (1 << 24)) >> 25; h8 += carry7; h7 -= carry7 << 25; carry4 = (h4 + (int64_t) (1 << 25)) >> 26; h5 += carry4; h4 -= carry4 << 26; carry8 = (h8 + (int64_t) (1 << 25)) >> 26; h9 += carry8; h8 -= carry8 << 26; carry9 = (h9 + (int64_t) (1 << 24)) >> 25; h0 += carry9 * 19; h9 -= carry9 << 25; carry0 = (h0 + (int64_t) (1 << 25)) >> 26; h1 += carry0; h0 -= carry0 << 26; h[0] = (int32_t) h0; h[1] = (int32_t) h1; h[2] = (int32_t) h2; h[3] = (int32_t) h3; h[4] = (int32_t) h4; h[5] = (int32_t) h5; h[6] = (int32_t) h6; h[7] = (int32_t) h7; h[8] = (int32_t) h8; h[9] = (int32_t) h9; } /* h = f - g Can overlap h with f or g. Preconditions: |f| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. |g| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. Postconditions: |h| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. */ void fe_sub(fe h, const fe f, const fe g) { int32_t f0 = f[0]; int32_t f1 = f[1]; int32_t f2 = f[2]; int32_t f3 = f[3]; int32_t f4 = f[4]; int32_t f5 = f[5]; int32_t f6 = f[6]; int32_t f7 = f[7]; int32_t f8 = f[8]; int32_t f9 = f[9]; int32_t g0 = g[0]; int32_t g1 = g[1]; int32_t g2 = g[2]; int32_t g3 = g[3]; int32_t g4 = g[4]; int32_t g5 = g[5]; int32_t g6 = g[6]; int32_t g7 = g[7]; int32_t g8 = g[8]; int32_t g9 = g[9]; int32_t h0 = f0 - g0; int32_t h1 = f1 - g1; int32_t h2 = f2 - g2; int32_t h3 = f3 - g3; int32_t h4 = f4 - g4; int32_t h5 = f5 - g5; int32_t h6 = f6 - g6; int32_t h7 = f7 - g7; int32_t h8 = f8 - g8; int32_t h9 = f9 - g9; h[0] = h0; h[1] = h1; h[2] = h2; h[3] = h3; h[4] = h4; h[5] = h5; h[6] = h6; h[7] = h7; h[8] = h8; h[9] = h9; } /* Preconditions: |h| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. Write p=2^255-19; q=floor(h/p). Basic claim: q = floor(2^(-255)(h + 19 2^(-25)h9 + 2^(-1))). Proof: Have |h|<=p so |q|<=1 so |19^2 2^(-255) q|<1/4. Also have |h-2^230 h9|<2^231 so |19 2^(-255)(h-2^230 h9)|<1/4. Write y=2^(-1)-19^2 2^(-255)q-19 2^(-255)(h-2^230 h9). Then 0> 25; q = (h0 + q) >> 26; q = (h1 + q) >> 25; q = (h2 + q) >> 26; q = (h3 + q) >> 25; q = (h4 + q) >> 26; q = (h5 + q) >> 25; q = (h6 + q) >> 26; q = (h7 + q) >> 25; q = (h8 + q) >> 26; q = (h9 + q) >> 25; /* Goal: Output h-(2^255-19)q, which is between 0 and 2^255-20. */ h0 += 19 * q; /* Goal: Output h-2^255 q, which is between 0 and 2^255-20. */ carry0 = h0 >> 26; h1 += carry0; h0 -= carry0 << 26; carry1 = h1 >> 25; h2 += carry1; h1 -= carry1 << 25; carry2 = h2 >> 26; h3 += carry2; h2 -= carry2 << 26; carry3 = h3 >> 25; h4 += carry3; h3 -= carry3 << 25; carry4 = h4 >> 26; h5 += carry4; h4 -= carry4 << 26; carry5 = h5 >> 25; h6 += carry5; h5 -= carry5 << 25; carry6 = h6 >> 26; h7 += carry6; h6 -= carry6 << 26; carry7 = h7 >> 25; h8 += carry7; h7 -= carry7 << 25; carry8 = h8 >> 26; h9 += carry8; h8 -= carry8 << 26; carry9 = h9 >> 25; h9 -= carry9 << 25; /* h10 = carry9 */ /* Goal: Output h0+...+2^255 h10-2^255 q, which is between 0 and 2^255-20. Have h0+...+2^230 h9 between 0 and 2^255-1; evidently 2^255 h10-2^255 q = 0. Goal: Output h0+...+2^230 h9. */ s[0] = (unsigned char) (h0 >> 0); s[1] = (unsigned char) (h0 >> 8); s[2] = (unsigned char) (h0 >> 16); s[3] = (unsigned char) ((h0 >> 24) | (h1 << 2)); s[4] = (unsigned char) (h1 >> 6); s[5] = (unsigned char) (h1 >> 14); s[6] = (unsigned char) ((h1 >> 22) | (h2 << 3)); s[7] = (unsigned char) (h2 >> 5); s[8] = (unsigned char) (h2 >> 13); s[9] = (unsigned char) ((h2 >> 21) | (h3 << 5)); s[10] = (unsigned char) (h3 >> 3); s[11] = (unsigned char) (h3 >> 11); s[12] = (unsigned char) ((h3 >> 19) | (h4 << 6)); s[13] = (unsigned char) (h4 >> 2); s[14] = (unsigned char) (h4 >> 10); s[15] = (unsigned char) (h4 >> 18); s[16] = (unsigned char) (h5 >> 0); s[17] = (unsigned char) (h5 >> 8); s[18] = (unsigned char) (h5 >> 16); s[19] = (unsigned char) ((h5 >> 24) | (h6 << 1)); s[20] = (unsigned char) (h6 >> 7); s[21] = (unsigned char) (h6 >> 15); s[22] = (unsigned char) ((h6 >> 23) | (h7 << 3)); s[23] = (unsigned char) (h7 >> 5); s[24] = (unsigned char) (h7 >> 13); s[25] = (unsigned char) ((h7 >> 21) | (h8 << 4)); s[26] = (unsigned char) (h8 >> 4); s[27] = (unsigned char) (h8 >> 12); s[28] = (unsigned char) ((h8 >> 20) | (h9 << 6)); s[29] = (unsigned char) (h9 >> 2); s[30] = (unsigned char) (h9 >> 10); s[31] = (unsigned char) (h9 >> 18); } opengnb-ver1.6.0.a/libs/ed25519/fe.h000066400000000000000000000017241500454252100165760ustar00rootroot00000000000000#ifndef FE_H #define FE_H #include "fixedint.h" /* fe means field element. Here the field is \Z/(2^255-19). An element t, entries t[0]...t[9], represents the integer t[0]+2^26 t[1]+2^51 t[2]+2^77 t[3]+2^102 t[4]+...+2^230 t[9]. Bounds on each t[i] vary depending on context. */ typedef int32_t fe[10]; void fe_0(fe h); void fe_1(fe h); void fe_frombytes(fe h, const unsigned char *s); void fe_tobytes(unsigned char *s, const fe h); void fe_copy(fe h, const fe f); int fe_isnegative(const fe f); int fe_isnonzero(const fe f); void fe_cmov(fe f, const fe g, unsigned int b); void fe_cswap(fe f, fe g, unsigned int b); void fe_neg(fe h, const fe f); void fe_add(fe h, const fe f, const fe g); void fe_invert(fe out, const fe z); void fe_sq(fe h, const fe f); void fe_sq2(fe h, const fe f); void fe_mul(fe h, const fe f, const fe g); void fe_mul121666(fe h, fe f); void fe_pow22523(fe out, const fe z); void fe_sub(fe h, const fe f, const fe g); #endif opengnb-ver1.6.0.a/libs/ed25519/fixedint.h000066400000000000000000000047261500454252100200230ustar00rootroot00000000000000/* Portable header to provide the 32 and 64 bits type. Not a compatible replacement for , do not blindly use it as such. */ #if ((defined(__STDC__) && __STDC__ && __STDC_VERSION__ >= 199901L) || (defined(__WATCOMC__) && (defined(_STDINT_H_INCLUDED) || __WATCOMC__ >= 1250)) || (defined(__GNUC__) && (defined(_STDINT_H) || defined(_STDINT_H_) || defined(__UINT_FAST64_TYPE__)) )) && !defined(FIXEDINT_H_INCLUDED) #include #define FIXEDINT_H_INCLUDED #if defined(__WATCOMC__) && __WATCOMC__ >= 1250 && !defined(UINT64_C) #include #define UINT64_C(x) (x + (UINT64_MAX - UINT64_MAX)) #endif #endif #ifndef FIXEDINT_H_INCLUDED #define FIXEDINT_H_INCLUDED #include /* (u)int32_t */ #ifndef uint32_t #if (ULONG_MAX == 0xffffffffUL) typedef unsigned long uint32_t; #elif (UINT_MAX == 0xffffffffUL) typedef unsigned int uint32_t; #elif (USHRT_MAX == 0xffffffffUL) typedef unsigned short uint32_t; #endif #endif #ifndef int32_t #if (LONG_MAX == 0x7fffffffL) typedef signed long int32_t; #elif (INT_MAX == 0x7fffffffL) typedef signed int int32_t; #elif (SHRT_MAX == 0x7fffffffL) typedef signed short int32_t; #endif #endif /* (u)int64_t */ #if (defined(__STDC__) && defined(__STDC_VERSION__) && __STDC__ && __STDC_VERSION__ >= 199901L) typedef long long int64_t; typedef unsigned long long uint64_t; #define UINT64_C(v) v ##ULL #define INT64_C(v) v ##LL #elif defined(__GNUC__) __extension__ typedef long long int64_t; __extension__ typedef unsigned long long uint64_t; #define UINT64_C(v) v ##ULL #define INT64_C(v) v ##LL #elif defined(__MWERKS__) || defined(__SUNPRO_C) || defined(__SUNPRO_CC) || defined(__APPLE_CC__) || defined(_LONG_LONG) || defined(_CRAYC) typedef long long int64_t; typedef unsigned long long uint64_t; #define UINT64_C(v) v ##ULL #define INT64_C(v) v ##LL #elif (defined(__WATCOMC__) && defined(__WATCOM_INT64__)) || (defined(_MSC_VER) && _INTEGRAL_MAX_BITS >= 64) || (defined(__BORLANDC__) && __BORLANDC__ > 0x460) || defined(__alpha) || defined(__DECC) typedef __int64 int64_t; typedef unsigned __int64 uint64_t; #define UINT64_C(v) v ##UI64 #define INT64_C(v) v ##I64 #endif #endif opengnb-ver1.6.0.a/libs/ed25519/ge.c000066400000000000000000000242051500454252100165710ustar00rootroot00000000000000#include "ge.h" #include "precomp_data.h" /* r = p + q */ void ge_add(ge_p1p1 *r, const ge_p3 *p, const ge_cached *q) { fe t0; fe_add(r->X, p->Y, p->X); fe_sub(r->Y, p->Y, p->X); fe_mul(r->Z, r->X, q->YplusX); fe_mul(r->Y, r->Y, q->YminusX); fe_mul(r->T, q->T2d, p->T); fe_mul(r->X, p->Z, q->Z); fe_add(t0, r->X, r->X); fe_sub(r->X, r->Z, r->Y); fe_add(r->Y, r->Z, r->Y); fe_add(r->Z, t0, r->T); fe_sub(r->T, t0, r->T); } static void slide(signed char *r, const unsigned char *a) { int i; int b; int k; for (i = 0; i < 256; ++i) { r[i] = 1 & (a[i >> 3] >> (i & 7)); } for (i = 0; i < 256; ++i) if (r[i]) { for (b = 1; b <= 6 && i + b < 256; ++b) { if (r[i + b]) { if (r[i] + (r[i + b] << b) <= 15) { r[i] += r[i + b] << b; r[i + b] = 0; } else if (r[i] - (r[i + b] << b) >= -15) { r[i] -= r[i + b] << b; for (k = i + b; k < 256; ++k) { if (!r[k]) { r[k] = 1; break; } r[k] = 0; } } else { break; } } } } } /* r = a * A + b * B where a = a[0]+256*a[1]+...+256^31 a[31]. and b = b[0]+256*b[1]+...+256^31 b[31]. B is the Ed25519 base point (x,4/5) with x positive. */ void ge_double_scalarmult_vartime(ge_p2 *r, const unsigned char *a, const ge_p3 *A, const unsigned char *b) { signed char aslide[256]; signed char bslide[256]; ge_cached Ai[8]; /* A,3A,5A,7A,9A,11A,13A,15A */ ge_p1p1 t; ge_p3 u; ge_p3 A2; int i; slide(aslide, a); slide(bslide, b); ge_p3_to_cached(&Ai[0], A); ge_p3_dbl(&t, A); ge_p1p1_to_p3(&A2, &t); ge_add(&t, &A2, &Ai[0]); ge_p1p1_to_p3(&u, &t); ge_p3_to_cached(&Ai[1], &u); ge_add(&t, &A2, &Ai[1]); ge_p1p1_to_p3(&u, &t); ge_p3_to_cached(&Ai[2], &u); ge_add(&t, &A2, &Ai[2]); ge_p1p1_to_p3(&u, &t); ge_p3_to_cached(&Ai[3], &u); ge_add(&t, &A2, &Ai[3]); ge_p1p1_to_p3(&u, &t); ge_p3_to_cached(&Ai[4], &u); ge_add(&t, &A2, &Ai[4]); ge_p1p1_to_p3(&u, &t); ge_p3_to_cached(&Ai[5], &u); ge_add(&t, &A2, &Ai[5]); ge_p1p1_to_p3(&u, &t); ge_p3_to_cached(&Ai[6], &u); ge_add(&t, &A2, &Ai[6]); ge_p1p1_to_p3(&u, &t); ge_p3_to_cached(&Ai[7], &u); ge_p2_0(r); for (i = 255; i >= 0; --i) { if (aslide[i] || bslide[i]) { break; } } for (; i >= 0; --i) { ge_p2_dbl(&t, r); if (aslide[i] > 0) { ge_p1p1_to_p3(&u, &t); ge_add(&t, &u, &Ai[aslide[i] / 2]); } else if (aslide[i] < 0) { ge_p1p1_to_p3(&u, &t); ge_sub(&t, &u, &Ai[(-aslide[i]) / 2]); } if (bslide[i] > 0) { ge_p1p1_to_p3(&u, &t); ge_madd(&t, &u, &Bi[bslide[i] / 2]); } else if (bslide[i] < 0) { ge_p1p1_to_p3(&u, &t); ge_msub(&t, &u, &Bi[(-bslide[i]) / 2]); } ge_p1p1_to_p2(r, &t); } } static const fe d = { -10913610, 13857413, -15372611, 6949391, 114729, -8787816, -6275908, -3247719, -18696448, -12055116 }; static const fe sqrtm1 = { -32595792, -7943725, 9377950, 3500415, 12389472, -272473, -25146209, -2005654, 326686, 11406482 }; int ge_frombytes_negate_vartime(ge_p3 *h, const unsigned char *s) { fe u; fe v; fe v3; fe vxx; fe check; fe_frombytes(h->Y, s); fe_1(h->Z); fe_sq(u, h->Y); fe_mul(v, u, d); fe_sub(u, u, h->Z); /* u = y^2-1 */ fe_add(v, v, h->Z); /* v = dy^2+1 */ fe_sq(v3, v); fe_mul(v3, v3, v); /* v3 = v^3 */ fe_sq(h->X, v3); fe_mul(h->X, h->X, v); fe_mul(h->X, h->X, u); /* x = uv^7 */ fe_pow22523(h->X, h->X); /* x = (uv^7)^((q-5)/8) */ fe_mul(h->X, h->X, v3); fe_mul(h->X, h->X, u); /* x = uv^3(uv^7)^((q-5)/8) */ fe_sq(vxx, h->X); fe_mul(vxx, vxx, v); fe_sub(check, vxx, u); /* vx^2-u */ if (fe_isnonzero(check)) { fe_add(check, vxx, u); /* vx^2+u */ if (fe_isnonzero(check)) { return -1; } fe_mul(h->X, h->X, sqrtm1); } if (fe_isnegative(h->X) == (s[31] >> 7)) { fe_neg(h->X, h->X); } fe_mul(h->T, h->X, h->Y); return 0; } /* r = p + q */ void ge_madd(ge_p1p1 *r, const ge_p3 *p, const ge_precomp *q) { fe t0; fe_add(r->X, p->Y, p->X); fe_sub(r->Y, p->Y, p->X); fe_mul(r->Z, r->X, q->yplusx); fe_mul(r->Y, r->Y, q->yminusx); fe_mul(r->T, q->xy2d, p->T); fe_add(t0, p->Z, p->Z); fe_sub(r->X, r->Z, r->Y); fe_add(r->Y, r->Z, r->Y); fe_add(r->Z, t0, r->T); fe_sub(r->T, t0, r->T); } /* r = p - q */ void ge_msub(ge_p1p1 *r, const ge_p3 *p, const ge_precomp *q) { fe t0; fe_add(r->X, p->Y, p->X); fe_sub(r->Y, p->Y, p->X); fe_mul(r->Z, r->X, q->yminusx); fe_mul(r->Y, r->Y, q->yplusx); fe_mul(r->T, q->xy2d, p->T); fe_add(t0, p->Z, p->Z); fe_sub(r->X, r->Z, r->Y); fe_add(r->Y, r->Z, r->Y); fe_sub(r->Z, t0, r->T); fe_add(r->T, t0, r->T); } /* r = p */ void ge_p1p1_to_p2(ge_p2 *r, const ge_p1p1 *p) { fe_mul(r->X, p->X, p->T); fe_mul(r->Y, p->Y, p->Z); fe_mul(r->Z, p->Z, p->T); } /* r = p */ void ge_p1p1_to_p3(ge_p3 *r, const ge_p1p1 *p) { fe_mul(r->X, p->X, p->T); fe_mul(r->Y, p->Y, p->Z); fe_mul(r->Z, p->Z, p->T); fe_mul(r->T, p->X, p->Y); } void ge_p2_0(ge_p2 *h) { fe_0(h->X); fe_1(h->Y); fe_1(h->Z); } /* r = 2 * p */ void ge_p2_dbl(ge_p1p1 *r, const ge_p2 *p) { fe t0; fe_sq(r->X, p->X); fe_sq(r->Z, p->Y); fe_sq2(r->T, p->Z); fe_add(r->Y, p->X, p->Y); fe_sq(t0, r->Y); fe_add(r->Y, r->Z, r->X); fe_sub(r->Z, r->Z, r->X); fe_sub(r->X, t0, r->Y); fe_sub(r->T, r->T, r->Z); } void ge_p3_0(ge_p3 *h) { fe_0(h->X); fe_1(h->Y); fe_1(h->Z); fe_0(h->T); } /* r = 2 * p */ void ge_p3_dbl(ge_p1p1 *r, const ge_p3 *p) { ge_p2 q; ge_p3_to_p2(&q, p); ge_p2_dbl(r, &q); } /* r = p */ static const fe d2 = { -21827239, -5839606, -30745221, 13898782, 229458, 15978800, -12551817, -6495438, 29715968, 9444199 }; void ge_p3_to_cached(ge_cached *r, const ge_p3 *p) { fe_add(r->YplusX, p->Y, p->X); fe_sub(r->YminusX, p->Y, p->X); fe_copy(r->Z, p->Z); fe_mul(r->T2d, p->T, d2); } /* r = p */ void ge_p3_to_p2(ge_p2 *r, const ge_p3 *p) { fe_copy(r->X, p->X); fe_copy(r->Y, p->Y); fe_copy(r->Z, p->Z); } void ge_p3_tobytes(unsigned char *s, const ge_p3 *h) { fe recip; fe x; fe y; fe_invert(recip, h->Z); fe_mul(x, h->X, recip); fe_mul(y, h->Y, recip); fe_tobytes(s, y); s[31] ^= fe_isnegative(x) << 7; } static unsigned char equal(signed char b, signed char c) { unsigned char ub = b; unsigned char uc = c; unsigned char x = ub ^ uc; /* 0: yes; 1..255: no */ uint64_t y = x; /* 0: yes; 1..255: no */ y -= 1; /* large: yes; 0..254: no */ y >>= 63; /* 1: yes; 0: no */ return (unsigned char) y; } static unsigned char negative(signed char b) { uint64_t x = b; /* 18446744073709551361..18446744073709551615: yes; 0..255: no */ x >>= 63; /* 1: yes; 0: no */ return (unsigned char) x; } static void cmov(ge_precomp *t, const ge_precomp *u, unsigned char b) { fe_cmov(t->yplusx, u->yplusx, b); fe_cmov(t->yminusx, u->yminusx, b); fe_cmov(t->xy2d, u->xy2d, b); } static void select(ge_precomp *t, int pos, signed char b) { ge_precomp minust; unsigned char bnegative = negative(b); unsigned char babs = b - (((-bnegative) & b) << 1); fe_1(t->yplusx); fe_1(t->yminusx); fe_0(t->xy2d); cmov(t, &base[pos][0], equal(babs, 1)); cmov(t, &base[pos][1], equal(babs, 2)); cmov(t, &base[pos][2], equal(babs, 3)); cmov(t, &base[pos][3], equal(babs, 4)); cmov(t, &base[pos][4], equal(babs, 5)); cmov(t, &base[pos][5], equal(babs, 6)); cmov(t, &base[pos][6], equal(babs, 7)); cmov(t, &base[pos][7], equal(babs, 8)); fe_copy(minust.yplusx, t->yminusx); fe_copy(minust.yminusx, t->yplusx); fe_neg(minust.xy2d, t->xy2d); cmov(t, &minust, bnegative); } /* h = a * B where a = a[0]+256*a[1]+...+256^31 a[31] B is the Ed25519 base point (x,4/5) with x positive. Preconditions: a[31] <= 127 */ void ge_scalarmult_base(ge_p3 *h, const unsigned char *a) { signed char e[64]; signed char carry; ge_p1p1 r; ge_p2 s; ge_precomp t; int i; for (i = 0; i < 32; ++i) { e[2 * i + 0] = (a[i] >> 0) & 15; e[2 * i + 1] = (a[i] >> 4) & 15; } /* each e[i] is between 0 and 15 */ /* e[63] is between 0 and 7 */ carry = 0; for (i = 0; i < 63; ++i) { e[i] += carry; carry = e[i] + 8; carry >>= 4; e[i] -= carry << 4; } e[63] += carry; /* each e[i] is between -8 and 8 */ ge_p3_0(h); for (i = 1; i < 64; i += 2) { select(&t, i / 2, e[i]); ge_madd(&r, h, &t); ge_p1p1_to_p3(h, &r); } ge_p3_dbl(&r, h); ge_p1p1_to_p2(&s, &r); ge_p2_dbl(&r, &s); ge_p1p1_to_p2(&s, &r); ge_p2_dbl(&r, &s); ge_p1p1_to_p2(&s, &r); ge_p2_dbl(&r, &s); ge_p1p1_to_p3(h, &r); for (i = 0; i < 64; i += 2) { select(&t, i / 2, e[i]); ge_madd(&r, h, &t); ge_p1p1_to_p3(h, &r); } } /* r = p - q */ void ge_sub(ge_p1p1 *r, const ge_p3 *p, const ge_cached *q) { fe t0; fe_add(r->X, p->Y, p->X); fe_sub(r->Y, p->Y, p->X); fe_mul(r->Z, r->X, q->YminusX); fe_mul(r->Y, r->Y, q->YplusX); fe_mul(r->T, q->T2d, p->T); fe_mul(r->X, p->Z, q->Z); fe_add(t0, r->X, r->X); fe_sub(r->X, r->Z, r->Y); fe_add(r->Y, r->Z, r->Y); fe_sub(r->Z, t0, r->T); fe_add(r->T, t0, r->T); } void ge_tobytes(unsigned char *s, const ge_p2 *h) { fe recip; fe x; fe y; fe_invert(recip, h->Z); fe_mul(x, h->X, recip); fe_mul(y, h->Y, recip); fe_tobytes(s, y); s[31] ^= fe_isnegative(x) << 7; } opengnb-ver1.6.0.a/libs/ed25519/ge.h000066400000000000000000000032231500454252100165730ustar00rootroot00000000000000#ifndef GE_H #define GE_H #include "fe.h" /* ge means group element. Here the group is the set of pairs (x,y) of field elements (see fe.h) satisfying -x^2 + y^2 = 1 + d x^2y^2 where d = -121665/121666. Representations: ge_p2 (projective): (X:Y:Z) satisfying x=X/Z, y=Y/Z ge_p3 (extended): (X:Y:Z:T) satisfying x=X/Z, y=Y/Z, XY=ZT ge_p1p1 (completed): ((X:Z),(Y:T)) satisfying x=X/Z, y=Y/T ge_precomp (Duif): (y+x,y-x,2dxy) */ typedef struct { fe X; fe Y; fe Z; } ge_p2; typedef struct { fe X; fe Y; fe Z; fe T; } ge_p3; typedef struct { fe X; fe Y; fe Z; fe T; } ge_p1p1; typedef struct { fe yplusx; fe yminusx; fe xy2d; } ge_precomp; typedef struct { fe YplusX; fe YminusX; fe Z; fe T2d; } ge_cached; void ge_p3_tobytes(unsigned char *s, const ge_p3 *h); void ge_tobytes(unsigned char *s, const ge_p2 *h); int ge_frombytes_negate_vartime(ge_p3 *h, const unsigned char *s); void ge_add(ge_p1p1 *r, const ge_p3 *p, const ge_cached *q); void ge_sub(ge_p1p1 *r, const ge_p3 *p, const ge_cached *q); void ge_double_scalarmult_vartime(ge_p2 *r, const unsigned char *a, const ge_p3 *A, const unsigned char *b); void ge_madd(ge_p1p1 *r, const ge_p3 *p, const ge_precomp *q); void ge_msub(ge_p1p1 *r, const ge_p3 *p, const ge_precomp *q); void ge_scalarmult_base(ge_p3 *h, const unsigned char *a); void ge_p1p1_to_p2(ge_p2 *r, const ge_p1p1 *p); void ge_p1p1_to_p3(ge_p3 *r, const ge_p1p1 *p); void ge_p2_0(ge_p2 *h); void ge_p2_dbl(ge_p1p1 *r, const ge_p2 *p); void ge_p3_0(ge_p3 *h); void ge_p3_dbl(ge_p1p1 *r, const ge_p3 *p); void ge_p3_to_cached(ge_cached *r, const ge_p3 *p); void ge_p3_to_p2(ge_p2 *r, const ge_p3 *p); #endif opengnb-ver1.6.0.a/libs/ed25519/key_exchange.c000066400000000000000000000034311500454252100206260ustar00rootroot00000000000000#include "ed25519.h" #include "fe.h" void ed25519_key_exchange(unsigned char *shared_secret, const unsigned char *public_key, const unsigned char *private_key) { unsigned char e[32]; unsigned int i; fe x1; fe x2; fe z2; fe x3; fe z3; fe tmp0; fe tmp1; int pos; unsigned int swap; unsigned int b; /* copy the private key and make sure it's valid */ for (i = 0; i < 32; ++i) { e[i] = private_key[i]; } e[0] &= 248; e[31] &= 63; e[31] |= 64; /* unpack the public key and convert edwards to montgomery */ /* due to CodesInChaos: montgomeryX = (edwardsY + 1)*inverse(1 - edwardsY) mod p */ fe_frombytes(x1, public_key); fe_1(tmp1); fe_add(tmp0, x1, tmp1); fe_sub(tmp1, tmp1, x1); fe_invert(tmp1, tmp1); fe_mul(x1, tmp0, tmp1); fe_1(x2); fe_0(z2); fe_copy(x3, x1); fe_1(z3); swap = 0; for (pos = 254; pos >= 0; --pos) { b = e[pos / 8] >> (pos & 7); b &= 1; swap ^= b; fe_cswap(x2, x3, swap); fe_cswap(z2, z3, swap); swap = b; /* from montgomery.h */ fe_sub(tmp0, x3, z3); fe_sub(tmp1, x2, z2); fe_add(x2, x2, z2); fe_add(z2, x3, z3); fe_mul(z3, tmp0, x2); fe_mul(z2, z2, tmp1); fe_sq(tmp0, tmp1); fe_sq(tmp1, x2); fe_add(x3, z3, z2); fe_sub(z2, z3, z2); fe_mul(x2, tmp1, tmp0); fe_sub(tmp1, tmp1, tmp0); fe_sq(z2, z2); fe_mul121666(z3, tmp1); fe_sq(x3, x3); fe_add(tmp0, tmp0, z3); fe_mul(z3, x1, z2); fe_mul(z2, tmp1, tmp0); } fe_cswap(x2, x3, swap); fe_cswap(z2, z3, swap); fe_invert(z2, z2); fe_mul(x2, x2, z2); fe_tobytes(shared_secret, x2); } opengnb-ver1.6.0.a/libs/ed25519/keypair.c000066400000000000000000000005741500454252100176450ustar00rootroot00000000000000#include "ed25519.h" #include "sha512.h" #include "ge.h" void ed25519_create_keypair(unsigned char *public_key, unsigned char *private_key, const unsigned char *seed) { ge_p3 A; sha512(seed, 32, private_key); private_key[0] &= 248; private_key[31] &= 63; private_key[31] |= 64; ge_scalarmult_base(&A, private_key); ge_p3_tobytes(public_key, &A); } opengnb-ver1.6.0.a/libs/ed25519/license.txt000066400000000000000000000015521500454252100202150ustar00rootroot00000000000000Copyright (c) 2015 Orson Peters This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. opengnb-ver1.6.0.a/libs/ed25519/precomp_data.h000066400000000000000000002770101500454252100206450ustar00rootroot00000000000000static const ge_precomp Bi[8] = { { { 25967493, -14356035, 29566456, 3660896, -12694345, 4014787, 27544626, -11754271, -6079156, 2047605 }, { -12545711, 934262, -2722910, 3049990, -727428, 9406986, 12720692, 5043384, 19500929, -15469378 }, { -8738181, 4489570, 9688441, -14785194, 10184609, -12363380, 29287919, 11864899, -24514362, -4438546 }, }, { { 15636291, -9688557, 24204773, -7912398, 616977, -16685262, 27787600, -14772189, 28944400, -1550024 }, { 16568933, 4717097, -11556148, -1102322, 15682896, -11807043, 16354577, -11775962, 7689662, 11199574 }, { 30464156, -5976125, -11779434, -15670865, 23220365, 15915852, 7512774, 10017326, -17749093, -9920357 }, }, { { 10861363, 11473154, 27284546, 1981175, -30064349, 12577861, 32867885, 14515107, -15438304, 10819380 }, { 4708026, 6336745, 20377586, 9066809, -11272109, 6594696, -25653668, 12483688, -12668491, 5581306 }, { 19563160, 16186464, -29386857, 4097519, 10237984, -4348115, 28542350, 13850243, -23678021, -15815942 }, }, { { 5153746, 9909285, 1723747, -2777874, 30523605, 5516873, 19480852, 5230134, -23952439, -15175766 }, { -30269007, -3463509, 7665486, 10083793, 28475525, 1649722, 20654025, 16520125, 30598449, 7715701 }, { 28881845, 14381568, 9657904, 3680757, -20181635, 7843316, -31400660, 1370708, 29794553, -1409300 }, }, { { -22518993, -6692182, 14201702, -8745502, -23510406, 8844726, 18474211, -1361450, -13062696, 13821877 }, { -6455177, -7839871, 3374702, -4740862, -27098617, -10571707, 31655028, -7212327, 18853322, -14220951 }, { 4566830, -12963868, -28974889, -12240689, -7602672, -2830569, -8514358, -10431137, 2207753, -3209784 }, }, { { -25154831, -4185821, 29681144, 7868801, -6854661, -9423865, -12437364, -663000, -31111463, -16132436 }, { 25576264, -2703214, 7349804, -11814844, 16472782, 9300885, 3844789, 15725684, 171356, 6466918 }, { 23103977, 13316479, 9739013, -16149481, 817875, -15038942, 8965339, -14088058, -30714912, 16193877 }, }, { { -33521811, 3180713, -2394130, 14003687, -16903474, -16270840, 17238398, 4729455, -18074513, 9256800 }, { -25182317, -4174131, 32336398, 5036987, -21236817, 11360617, 22616405, 9761698, -19827198, 630305 }, { -13720693, 2639453, -24237460, -7406481, 9494427, -5774029, -6554551, -15960994, -2449256, -14291300 }, }, { { -3151181, -5046075, 9282714, 6866145, -31907062, -863023, -18940575, 15033784, 25105118, -7894876 }, { -24326370, 15950226, -31801215, -14592823, -11662737, -5090925, 1573892, -2625887, 2198790, -15804619 }, { -3099351, 10324967, -2241613, 7453183, -5446979, -2735503, -13812022, -16236442, -32461234, -12290683 }, }, }; /* base[i][j] = (j+1)*256^i*B */ static const ge_precomp base[32][8] = { { { { 25967493, -14356035, 29566456, 3660896, -12694345, 4014787, 27544626, -11754271, -6079156, 2047605 }, { -12545711, 934262, -2722910, 3049990, -727428, 9406986, 12720692, 5043384, 19500929, -15469378 }, { -8738181, 4489570, 9688441, -14785194, 10184609, -12363380, 29287919, 11864899, -24514362, -4438546 }, }, { { -12815894, -12976347, -21581243, 11784320, -25355658, -2750717, -11717903, -3814571, -358445, -10211303 }, { -21703237, 6903825, 27185491, 6451973, -29577724, -9554005, -15616551, 11189268, -26829678, -5319081 }, { 26966642, 11152617, 32442495, 15396054, 14353839, -12752335, -3128826, -9541118, -15472047, -4166697 }, }, { { 15636291, -9688557, 24204773, -7912398, 616977, -16685262, 27787600, -14772189, 28944400, -1550024 }, { 16568933, 4717097, -11556148, -1102322, 15682896, -11807043, 16354577, -11775962, 7689662, 11199574 }, { 30464156, -5976125, -11779434, -15670865, 23220365, 15915852, 7512774, 10017326, -17749093, -9920357 }, }, { { -17036878, 13921892, 10945806, -6033431, 27105052, -16084379, -28926210, 15006023, 3284568, -6276540 }, { 23599295, -8306047, -11193664, -7687416, 13236774, 10506355, 7464579, 9656445, 13059162, 10374397 }, { 7798556, 16710257, 3033922, 2874086, 28997861, 2835604, 32406664, -3839045, -641708, -101325 }, }, { { 10861363, 11473154, 27284546, 1981175, -30064349, 12577861, 32867885, 14515107, -15438304, 10819380 }, { 4708026, 6336745, 20377586, 9066809, -11272109, 6594696, -25653668, 12483688, -12668491, 5581306 }, { 19563160, 16186464, -29386857, 4097519, 10237984, -4348115, 28542350, 13850243, -23678021, -15815942 }, }, { { -15371964, -12862754, 32573250, 4720197, -26436522, 5875511, -19188627, -15224819, -9818940, -12085777 }, { -8549212, 109983, 15149363, 2178705, 22900618, 4543417, 3044240, -15689887, 1762328, 14866737 }, { -18199695, -15951423, -10473290, 1707278, -17185920, 3916101, -28236412, 3959421, 27914454, 4383652 }, }, { { 5153746, 9909285, 1723747, -2777874, 30523605, 5516873, 19480852, 5230134, -23952439, -15175766 }, { -30269007, -3463509, 7665486, 10083793, 28475525, 1649722, 20654025, 16520125, 30598449, 7715701 }, { 28881845, 14381568, 9657904, 3680757, -20181635, 7843316, -31400660, 1370708, 29794553, -1409300 }, }, { { 14499471, -2729599, -33191113, -4254652, 28494862, 14271267, 30290735, 10876454, -33154098, 2381726 }, { -7195431, -2655363, -14730155, 462251, -27724326, 3941372, -6236617, 3696005, -32300832, 15351955 }, { 27431194, 8222322, 16448760, -3907995, -18707002, 11938355, -32961401, -2970515, 29551813, 10109425 }, }, }, { { { -13657040, -13155431, -31283750, 11777098, 21447386, 6519384, -2378284, -1627556, 10092783, -4764171 }, { 27939166, 14210322, 4677035, 16277044, -22964462, -12398139, -32508754, 12005538, -17810127, 12803510 }, { 17228999, -15661624, -1233527, 300140, -1224870, -11714777, 30364213, -9038194, 18016357, 4397660 }, }, { { -10958843, -7690207, 4776341, -14954238, 27850028, -15602212, -26619106, 14544525, -17477504, 982639 }, { 29253598, 15796703, -2863982, -9908884, 10057023, 3163536, 7332899, -4120128, -21047696, 9934963 }, { 5793303, 16271923, -24131614, -10116404, 29188560, 1206517, -14747930, 4559895, -30123922, -10897950 }, }, { { -27643952, -11493006, 16282657, -11036493, 28414021, -15012264, 24191034, 4541697, -13338309, 5500568 }, { 12650548, -1497113, 9052871, 11355358, -17680037, -8400164, -17430592, 12264343, 10874051, 13524335 }, { 25556948, -3045990, 714651, 2510400, 23394682, -10415330, 33119038, 5080568, -22528059, 5376628 }, }, { { -26088264, -4011052, -17013699, -3537628, -6726793, 1920897, -22321305, -9447443, 4535768, 1569007 }, { -2255422, 14606630, -21692440, -8039818, 28430649, 8775819, -30494562, 3044290, 31848280, 12543772 }, { -22028579, 2943893, -31857513, 6777306, 13784462, -4292203, -27377195, -2062731, 7718482, 14474653 }, }, { { 2385315, 2454213, -22631320, 46603, -4437935, -15680415, 656965, -7236665, 24316168, -5253567 }, { 13741529, 10911568, -33233417, -8603737, -20177830, -1033297, 33040651, -13424532, -20729456, 8321686 }, { 21060490, -2212744, 15712757, -4336099, 1639040, 10656336, 23845965, -11874838, -9984458, 608372 }, }, { { -13672732, -15087586, -10889693, -7557059, -6036909, 11305547, 1123968, -6780577, 27229399, 23887 }, { -23244140, -294205, -11744728, 14712571, -29465699, -2029617, 12797024, -6440308, -1633405, 16678954 }, { -29500620, 4770662, -16054387, 14001338, 7830047, 9564805, -1508144, -4795045, -17169265, 4904953 }, }, { { 24059557, 14617003, 19037157, -15039908, 19766093, -14906429, 5169211, 16191880, 2128236, -4326833 }, { -16981152, 4124966, -8540610, -10653797, 30336522, -14105247, -29806336, 916033, -6882542, -2986532 }, { -22630907, 12419372, -7134229, -7473371, -16478904, 16739175, 285431, 2763829, 15736322, 4143876 }, }, { { 2379352, 11839345, -4110402, -5988665, 11274298, 794957, 212801, -14594663, 23527084, -16458268 }, { 33431127, -11130478, -17838966, -15626900, 8909499, 8376530, -32625340, 4087881, -15188911, -14416214 }, { 1767683, 7197987, -13205226, -2022635, -13091350, 448826, 5799055, 4357868, -4774191, -16323038 }, }, }, { { { 6721966, 13833823, -23523388, -1551314, 26354293, -11863321, 23365147, -3949732, 7390890, 2759800 }, { 4409041, 2052381, 23373853, 10530217, 7676779, -12885954, 21302353, -4264057, 1244380, -12919645 }, { -4421239, 7169619, 4982368, -2957590, 30256825, -2777540, 14086413, 9208236, 15886429, 16489664 }, }, { { 1996075, 10375649, 14346367, 13311202, -6874135, -16438411, -13693198, 398369, -30606455, -712933 }, { -25307465, 9795880, -2777414, 14878809, -33531835, 14780363, 13348553, 12076947, -30836462, 5113182 }, { -17770784, 11797796, 31950843, 13929123, -25888302, 12288344, -30341101, -7336386, 13847711, 5387222 }, }, { { -18582163, -3416217, 17824843, -2340966, 22744343, -10442611, 8763061, 3617786, -19600662, 10370991 }, { 20246567, -14369378, 22358229, -543712, 18507283, -10413996, 14554437, -8746092, 32232924, 16763880 }, { 9648505, 10094563, 26416693, 14745928, -30374318, -6472621, 11094161, 15689506, 3140038, -16510092 }, }, { { -16160072, 5472695, 31895588, 4744994, 8823515, 10365685, -27224800, 9448613, -28774454, 366295 }, { 19153450, 11523972, -11096490, -6503142, -24647631, 5420647, 28344573, 8041113, 719605, 11671788 }, { 8678025, 2694440, -6808014, 2517372, 4964326, 11152271, -15432916, -15266516, 27000813, -10195553 }, }, { { -15157904, 7134312, 8639287, -2814877, -7235688, 10421742, 564065, 5336097, 6750977, -14521026 }, { 11836410, -3979488, 26297894, 16080799, 23455045, 15735944, 1695823, -8819122, 8169720, 16220347 }, { -18115838, 8653647, 17578566, -6092619, -8025777, -16012763, -11144307, -2627664, -5990708, -14166033 }, }, { { -23308498, -10968312, 15213228, -10081214, -30853605, -11050004, 27884329, 2847284, 2655861, 1738395 }, { -27537433, -14253021, -25336301, -8002780, -9370762, 8129821, 21651608, -3239336, -19087449, -11005278 }, { 1533110, 3437855, 23735889, 459276, 29970501, 11335377, 26030092, 5821408, 10478196, 8544890 }, }, { { 32173121, -16129311, 24896207, 3921497, 22579056, -3410854, 19270449, 12217473, 17789017, -3395995 }, { -30552961, -2228401, -15578829, -10147201, 13243889, 517024, 15479401, -3853233, 30460520, 1052596 }, { -11614875, 13323618, 32618793, 8175907, -15230173, 12596687, 27491595, -4612359, 3179268, -9478891 }, }, { { 31947069, -14366651, -4640583, -15339921, -15125977, -6039709, -14756777, -16411740, 19072640, -9511060 }, { 11685058, 11822410, 3158003, -13952594, 33402194, -4165066, 5977896, -5215017, 473099, 5040608 }, { -20290863, 8198642, -27410132, 11602123, 1290375, -2799760, 28326862, 1721092, -19558642, -3131606 }, }, }, { { { 7881532, 10687937, 7578723, 7738378, -18951012, -2553952, 21820786, 8076149, -27868496, 11538389 }, { -19935666, 3899861, 18283497, -6801568, -15728660, -11249211, 8754525, 7446702, -5676054, 5797016 }, { -11295600, -3793569, -15782110, -7964573, 12708869, -8456199, 2014099, -9050574, -2369172, -5877341 }, }, { { -22472376, -11568741, -27682020, 1146375, 18956691, 16640559, 1192730, -3714199, 15123619, 10811505 }, { 14352098, -3419715, -18942044, 10822655, 32750596, 4699007, -70363, 15776356, -28886779, -11974553 }, { -28241164, -8072475, -4978962, -5315317, 29416931, 1847569, -20654173, -16484855, 4714547, -9600655 }, }, { { 15200332, 8368572, 19679101, 15970074, -31872674, 1959451, 24611599, -4543832, -11745876, 12340220 }, { 12876937, -10480056, 33134381, 6590940, -6307776, 14872440, 9613953, 8241152, 15370987, 9608631 }, { -4143277, -12014408, 8446281, -391603, 4407738, 13629032, -7724868, 15866074, -28210621, -8814099 }, }, { { 26660628, -15677655, 8393734, 358047, -7401291, 992988, -23904233, 858697, 20571223, 8420556 }, { 14620715, 13067227, -15447274, 8264467, 14106269, 15080814, 33531827, 12516406, -21574435, -12476749 }, { 236881, 10476226, 57258, -14677024, 6472998, 2466984, 17258519, 7256740, 8791136, 15069930 }, }, { { 1276410, -9371918, 22949635, -16322807, -23493039, -5702186, 14711875, 4874229, -30663140, -2331391 }, { 5855666, 4990204, -13711848, 7294284, -7804282, 1924647, -1423175, -7912378, -33069337, 9234253 }, { 20590503, -9018988, 31529744, -7352666, -2706834, 10650548, 31559055, -11609587, 18979186, 13396066 }, }, { { 24474287, 4968103, 22267082, 4407354, 24063882, -8325180, -18816887, 13594782, 33514650, 7021958 }, { -11566906, -6565505, -21365085, 15928892, -26158305, 4315421, -25948728, -3916677, -21480480, 12868082 }, { -28635013, 13504661, 19988037, -2132761, 21078225, 6443208, -21446107, 2244500, -12455797, -8089383 }, }, { { -30595528, 13793479, -5852820, 319136, -25723172, -6263899, 33086546, 8957937, -15233648, 5540521 }, { -11630176, -11503902, -8119500, -7643073, 2620056, 1022908, -23710744, -1568984, -16128528, -14962807 }, { 23152971, 775386, 27395463, 14006635, -9701118, 4649512, 1689819, 892185, -11513277, -15205948 }, }, { { 9770129, 9586738, 26496094, 4324120, 1556511, -3550024, 27453819, 4763127, -19179614, 5867134 }, { -32765025, 1927590, 31726409, -4753295, 23962434, -16019500, 27846559, 5931263, -29749703, -16108455 }, { 27461885, -2977536, 22380810, 1815854, -23033753, -3031938, 7283490, -15148073, -19526700, 7734629 }, }, }, { { { -8010264, -9590817, -11120403, 6196038, 29344158, -13430885, 7585295, -3176626, 18549497, 15302069 }, { -32658337, -6171222, -7672793, -11051681, 6258878, 13504381, 10458790, -6418461, -8872242, 8424746 }, { 24687205, 8613276, -30667046, -3233545, 1863892, -1830544, 19206234, 7134917, -11284482, -828919 }, }, { { 11334899, -9218022, 8025293, 12707519, 17523892, -10476071, 10243738, -14685461, -5066034, 16498837 }, { 8911542, 6887158, -9584260, -6958590, 11145641, -9543680, 17303925, -14124238, 6536641, 10543906 }, { -28946384, 15479763, -17466835, 568876, -1497683, 11223454, -2669190, -16625574, -27235709, 8876771 }, }, { { -25742899, -12566864, -15649966, -846607, -33026686, -796288, -33481822, 15824474, -604426, -9039817 }, { 10330056, 70051, 7957388, -9002667, 9764902, 15609756, 27698697, -4890037, 1657394, 3084098 }, { 10477963, -7470260, 12119566, -13250805, 29016247, -5365589, 31280319, 14396151, -30233575, 15272409 }, }, { { -12288309, 3169463, 28813183, 16658753, 25116432, -5630466, -25173957, -12636138, -25014757, 1950504 }, { -26180358, 9489187, 11053416, -14746161, -31053720, 5825630, -8384306, -8767532, 15341279, 8373727 }, { 28685821, 7759505, -14378516, -12002860, -31971820, 4079242, 298136, -10232602, -2878207, 15190420 }, }, { { -32932876, 13806336, -14337485, -15794431, -24004620, 10940928, 8669718, 2742393, -26033313, -6875003 }, { -1580388, -11729417, -25979658, -11445023, -17411874, -10912854, 9291594, -16247779, -12154742, 6048605 }, { -30305315, 14843444, 1539301, 11864366, 20201677, 1900163, 13934231, 5128323, 11213262, 9168384 }, }, { { -26280513, 11007847, 19408960, -940758, -18592965, -4328580, -5088060, -11105150, 20470157, -16398701 }, { -23136053, 9282192, 14855179, -15390078, -7362815, -14408560, -22783952, 14461608, 14042978, 5230683 }, { 29969567, -2741594, -16711867, -8552442, 9175486, -2468974, 21556951, 3506042, -5933891, -12449708 }, }, { { -3144746, 8744661, 19704003, 4581278, -20430686, 6830683, -21284170, 8971513, -28539189, 15326563 }, { -19464629, 10110288, -17262528, -3503892, -23500387, 1355669, -15523050, 15300988, -20514118, 9168260 }, { -5353335, 4488613, -23803248, 16314347, 7780487, -15638939, -28948358, 9601605, 33087103, -9011387 }, }, { { -19443170, -15512900, -20797467, -12445323, -29824447, 10229461, -27444329, -15000531, -5996870, 15664672 }, { 23294591, -16632613, -22650781, -8470978, 27844204, 11461195, 13099750, -2460356, 18151676, 13417686 }, { -24722913, -4176517, -31150679, 5988919, -26858785, 6685065, 1661597, -12551441, 15271676, -15452665 }, }, }, { { { 11433042, -13228665, 8239631, -5279517, -1985436, -725718, -18698764, 2167544, -6921301, -13440182 }, { -31436171, 15575146, 30436815, 12192228, -22463353, 9395379, -9917708, -8638997, 12215110, 12028277 }, { 14098400, 6555944, 23007258, 5757252, -15427832, -12950502, 30123440, 4617780, -16900089, -655628 }, }, { { -4026201, -15240835, 11893168, 13718664, -14809462, 1847385, -15819999, 10154009, 23973261, -12684474 }, { -26531820, -3695990, -1908898, 2534301, -31870557, -16550355, 18341390, -11419951, 32013174, -10103539 }, { -25479301, 10876443, -11771086, -14625140, -12369567, 1838104, 21911214, 6354752, 4425632, -837822 }, }, { { -10433389, -14612966, 22229858, -3091047, -13191166, 776729, -17415375, -12020462, 4725005, 14044970 }, { 19268650, -7304421, 1555349, 8692754, -21474059, -9910664, 6347390, -1411784, -19522291, -16109756 }, { -24864089, 12986008, -10898878, -5558584, -11312371, -148526, 19541418, 8180106, 9282262, 10282508 }, }, { { -26205082, 4428547, -8661196, -13194263, 4098402, -14165257, 15522535, 8372215, 5542595, -10702683 }, { -10562541, 14895633, 26814552, -16673850, -17480754, -2489360, -2781891, 6993761, -18093885, 10114655 }, { -20107055, -929418, 31422704, 10427861, -7110749, 6150669, -29091755, -11529146, 25953725, -106158 }, }, { { -4234397, -8039292, -9119125, 3046000, 2101609, -12607294, 19390020, 6094296, -3315279, 12831125 }, { -15998678, 7578152, 5310217, 14408357, -33548620, -224739, 31575954, 6326196, 7381791, -2421839 }, { -20902779, 3296811, 24736065, -16328389, 18374254, 7318640, 6295303, 8082724, -15362489, 12339664 }, }, { { 27724736, 2291157, 6088201, -14184798, 1792727, 5857634, 13848414, 15768922, 25091167, 14856294 }, { -18866652, 8331043, 24373479, 8541013, -701998, -9269457, 12927300, -12695493, -22182473, -9012899 }, { -11423429, -5421590, 11632845, 3405020, 30536730, -11674039, -27260765, 13866390, 30146206, 9142070 }, }, { { 3924129, -15307516, -13817122, -10054960, 12291820, -668366, -27702774, 9326384, -8237858, 4171294 }, { -15921940, 16037937, 6713787, 16606682, -21612135, 2790944, 26396185, 3731949, 345228, -5462949 }, { -21327538, 13448259, 25284571, 1143661, 20614966, -8849387, 2031539, -12391231, -16253183, -13582083 }, }, { { 31016211, -16722429, 26371392, -14451233, -5027349, 14854137, 17477601, 3842657, 28012650, -16405420 }, { -5075835, 9368966, -8562079, -4600902, -15249953, 6970560, -9189873, 16292057, -8867157, 3507940 }, { 29439664, 3537914, 23333589, 6997794, -17555561, -11018068, -15209202, -15051267, -9164929, 6580396 }, }, }, { { { -12185861, -7679788, 16438269, 10826160, -8696817, -6235611, 17860444, -9273846, -2095802, 9304567 }, { 20714564, -4336911, 29088195, 7406487, 11426967, -5095705, 14792667, -14608617, 5289421, -477127 }, { -16665533, -10650790, -6160345, -13305760, 9192020, -1802462, 17271490, 12349094, 26939669, -3752294 }, }, { { -12889898, 9373458, 31595848, 16374215, 21471720, 13221525, -27283495, -12348559, -3698806, 117887 }, { 22263325, -6560050, 3984570, -11174646, -15114008, -566785, 28311253, 5358056, -23319780, 541964 }, { 16259219, 3261970, 2309254, -15534474, -16885711, -4581916, 24134070, -16705829, -13337066, -13552195 }, }, { { 9378160, -13140186, -22845982, -12745264, 28198281, -7244098, -2399684, -717351, 690426, 14876244 }, { 24977353, -314384, -8223969, -13465086, 28432343, -1176353, -13068804, -12297348, -22380984, 6618999 }, { -1538174, 11685646, 12944378, 13682314, -24389511, -14413193, 8044829, -13817328, 32239829, -5652762 }, }, { { -18603066, 4762990, -926250, 8885304, -28412480, -3187315, 9781647, -10350059, 32779359, 5095274 }, { -33008130, -5214506, -32264887, -3685216, 9460461, -9327423, -24601656, 14506724, 21639561, -2630236 }, { -16400943, -13112215, 25239338, 15531969, 3987758, -4499318, -1289502, -6863535, 17874574, 558605 }, }, { { -13600129, 10240081, 9171883, 16131053, -20869254, 9599700, 33499487, 5080151, 2085892, 5119761 }, { -22205145, -2519528, -16381601, 414691, -25019550, 2170430, 30634760, -8363614, -31999993, -5759884 }, { -6845704, 15791202, 8550074, -1312654, 29928809, -12092256, 27534430, -7192145, -22351378, 12961482 }, }, { { -24492060, -9570771, 10368194, 11582341, -23397293, -2245287, 16533930, 8206996, -30194652, -5159638 }, { -11121496, -3382234, 2307366, 6362031, -135455, 8868177, -16835630, 7031275, 7589640, 8945490 }, { -32152748, 8917967, 6661220, -11677616, -1192060, -15793393, 7251489, -11182180, 24099109, -14456170 }, }, { { 5019558, -7907470, 4244127, -14714356, -26933272, 6453165, -19118182, -13289025, -6231896, -10280736 }, { 10853594, 10721687, 26480089, 5861829, -22995819, 1972175, -1866647, -10557898, -3363451, -6441124 }, { -17002408, 5906790, 221599, -6563147, 7828208, -13248918, 24362661, -2008168, -13866408, 7421392 }, }, { { 8139927, -6546497, 32257646, -5890546, 30375719, 1886181, -21175108, 15441252, 28826358, -4123029 }, { 6267086, 9695052, 7709135, -16603597, -32869068, -1886135, 14795160, -7840124, 13746021, -1742048 }, { 28584902, 7787108, -6732942, -15050729, 22846041, -7571236, -3181936, -363524, 4771362, -8419958 }, }, }, { { { 24949256, 6376279, -27466481, -8174608, -18646154, -9930606, 33543569, -12141695, 3569627, 11342593 }, { 26514989, 4740088, 27912651, 3697550, 19331575, -11472339, 6809886, 4608608, 7325975, -14801071 }, { -11618399, -14554430, -24321212, 7655128, -1369274, 5214312, -27400540, 10258390, -17646694, -8186692 }, }, { { 11431204, 15823007, 26570245, 14329124, 18029990, 4796082, -31446179, 15580664, 9280358, -3973687 }, { -160783, -10326257, -22855316, -4304997, -20861367, -13621002, -32810901, -11181622, -15545091, 4387441 }, { -20799378, 12194512, 3937617, -5805892, -27154820, 9340370, -24513992, 8548137, 20617071, -7482001 }, }, { { -938825, -3930586, -8714311, 16124718, 24603125, -6225393, -13775352, -11875822, 24345683, 10325460 }, { -19855277, -1568885, -22202708, 8714034, 14007766, 6928528, 16318175, -1010689, 4766743, 3552007 }, { -21751364, -16730916, 1351763, -803421, -4009670, 3950935, 3217514, 14481909, 10988822, -3994762 }, }, { { 15564307, -14311570, 3101243, 5684148, 30446780, -8051356, 12677127, -6505343, -8295852, 13296005 }, { -9442290, 6624296, -30298964, -11913677, -4670981, -2057379, 31521204, 9614054, -30000824, 12074674 }, { 4771191, -135239, 14290749, -13089852, 27992298, 14998318, -1413936, -1556716, 29832613, -16391035 }, }, { { 7064884, -7541174, -19161962, -5067537, -18891269, -2912736, 25825242, 5293297, -27122660, 13101590 }, { -2298563, 2439670, -7466610, 1719965, -27267541, -16328445, 32512469, -5317593, -30356070, -4190957 }, { -30006540, 10162316, -33180176, 3981723, -16482138, -13070044, 14413974, 9515896, 19568978, 9628812 }, }, { { 33053803, 199357, 15894591, 1583059, 27380243, -4580435, -17838894, -6106839, -6291786, 3437740 }, { -18978877, 3884493, 19469877, 12726490, 15913552, 13614290, -22961733, 70104, 7463304, 4176122 }, { -27124001, 10659917, 11482427, -16070381, 12771467, -6635117, -32719404, -5322751, 24216882, 5944158 }, }, { { 8894125, 7450974, -2664149, -9765752, -28080517, -12389115, 19345746, 14680796, 11632993, 5847885 }, { 26942781, -2315317, 9129564, -4906607, 26024105, 11769399, -11518837, 6367194, -9727230, 4782140 }, { 19916461, -4828410, -22910704, -11414391, 25606324, -5972441, 33253853, 8220911, 6358847, -1873857 }, }, { { 801428, -2081702, 16569428, 11065167, 29875704, 96627, 7908388, -4480480, -13538503, 1387155 }, { 19646058, 5720633, -11416706, 12814209, 11607948, 12749789, 14147075, 15156355, -21866831, 11835260 }, { 19299512, 1155910, 28703737, 14890794, 2925026, 7269399, 26121523, 15467869, -26560550, 5052483 }, }, }, { { { -3017432, 10058206, 1980837, 3964243, 22160966, 12322533, -6431123, -12618185, 12228557, -7003677 }, { 32944382, 14922211, -22844894, 5188528, 21913450, -8719943, 4001465, 13238564, -6114803, 8653815 }, { 22865569, -4652735, 27603668, -12545395, 14348958, 8234005, 24808405, 5719875, 28483275, 2841751 }, }, { { -16420968, -1113305, -327719, -12107856, 21886282, -15552774, -1887966, -315658, 19932058, -12739203 }, { -11656086, 10087521, -8864888, -5536143, -19278573, -3055912, 3999228, 13239134, -4777469, -13910208 }, { 1382174, -11694719, 17266790, 9194690, -13324356, 9720081, 20403944, 11284705, -14013818, 3093230 }, }, { { 16650921, -11037932, -1064178, 1570629, -8329746, 7352753, -302424, 16271225, -24049421, -6691850 }, { -21911077, -5927941, -4611316, -5560156, -31744103, -10785293, 24123614, 15193618, -21652117, -16739389 }, { -9935934, -4289447, -25279823, 4372842, 2087473, 10399484, 31870908, 14690798, 17361620, 11864968 }, }, { { -11307610, 6210372, 13206574, 5806320, -29017692, -13967200, -12331205, -7486601, -25578460, -16240689 }, { 14668462, -12270235, 26039039, 15305210, 25515617, 4542480, 10453892, 6577524, 9145645, -6443880 }, { 5974874, 3053895, -9433049, -10385191, -31865124, 3225009, -7972642, 3936128, -5652273, -3050304 }, }, { { 30625386, -4729400, -25555961, -12792866, -20484575, 7695099, 17097188, -16303496, -27999779, 1803632 }, { -3553091, 9865099, -5228566, 4272701, -5673832, -16689700, 14911344, 12196514, -21405489, 7047412 }, { 20093277, 9920966, -11138194, -5343857, 13161587, 12044805, -32856851, 4124601, -32343828, -10257566 }, }, { { -20788824, 14084654, -13531713, 7842147, 19119038, -13822605, 4752377, -8714640, -21679658, 2288038 }, { -26819236, -3283715, 29965059, 3039786, -14473765, 2540457, 29457502, 14625692, -24819617, 12570232 }, { -1063558, -11551823, 16920318, 12494842, 1278292, -5869109, -21159943, -3498680, -11974704, 4724943 }, }, { { 17960970, -11775534, -4140968, -9702530, -8876562, -1410617, -12907383, -8659932, -29576300, 1903856 }, { 23134274, -14279132, -10681997, -1611936, 20684485, 15770816, -12989750, 3190296, 26955097, 14109738 }, { 15308788, 5320727, -30113809, -14318877, 22902008, 7767164, 29425325, -11277562, 31960942, 11934971 }, }, { { -27395711, 8435796, 4109644, 12222639, -24627868, 14818669, 20638173, 4875028, 10491392, 1379718 }, { -13159415, 9197841, 3875503, -8936108, -1383712, -5879801, 33518459, 16176658, 21432314, 12180697 }, { -11787308, 11500838, 13787581, -13832590, -22430679, 10140205, 1465425, 12689540, -10301319, -13872883 }, }, }, { { { 5414091, -15386041, -21007664, 9643570, 12834970, 1186149, -2622916, -1342231, 26128231, 6032912 }, { -26337395, -13766162, 32496025, -13653919, 17847801, -12669156, 3604025, 8316894, -25875034, -10437358 }, { 3296484, 6223048, 24680646, -12246460, -23052020, 5903205, -8862297, -4639164, 12376617, 3188849 }, }, { { 29190488, -14659046, 27549113, -1183516, 3520066, -10697301, 32049515, -7309113, -16109234, -9852307 }, { -14744486, -9309156, 735818, -598978, -20407687, -5057904, 25246078, -15795669, 18640741, -960977 }, { -6928835, -16430795, 10361374, 5642961, 4910474, 12345252, -31638386, -494430, 10530747, 1053335 }, }, { { -29265967, -14186805, -13538216, -12117373, -19457059, -10655384, -31462369, -2948985, 24018831, 15026644 }, { -22592535, -3145277, -2289276, 5953843, -13440189, 9425631, 25310643, 13003497, -2314791, -15145616 }, { -27419985, -603321, -8043984, -1669117, -26092265, 13987819, -27297622, 187899, -23166419, -2531735 }, }, { { -21744398, -13810475, 1844840, 5021428, -10434399, -15911473, 9716667, 16266922, -5070217, 726099 }, { 29370922, -6053998, 7334071, -15342259, 9385287, 2247707, -13661962, -4839461, 30007388, -15823341 }, { -936379, 16086691, 23751945, -543318, -1167538, -5189036, 9137109, 730663, 9835848, 4555336 }, }, { { -23376435, 1410446, -22253753, -12899614, 30867635, 15826977, 17693930, 544696, -11985298, 12422646 }, { 31117226, -12215734, -13502838, 6561947, -9876867, -12757670, -5118685, -4096706, 29120153, 13924425 }, { -17400879, -14233209, 19675799, -2734756, -11006962, -5858820, -9383939, -11317700, 7240931, -237388 }, }, { { -31361739, -11346780, -15007447, -5856218, -22453340, -12152771, 1222336, 4389483, 3293637, -15551743 }, { -16684801, -14444245, 11038544, 11054958, -13801175, -3338533, -24319580, 7733547, 12796905, -6335822 }, { -8759414, -10817836, -25418864, 10783769, -30615557, -9746811, -28253339, 3647836, 3222231, -11160462 }, }, { { 18606113, 1693100, -25448386, -15170272, 4112353, 10045021, 23603893, -2048234, -7550776, 2484985 }, { 9255317, -3131197, -12156162, -1004256, 13098013, -9214866, 16377220, -2102812, -19802075, -3034702 }, { -22729289, 7496160, -5742199, 11329249, 19991973, -3347502, -31718148, 9936966, -30097688, -10618797 }, }, { { 21878590, -5001297, 4338336, 13643897, -3036865, 13160960, 19708896, 5415497, -7360503, -4109293 }, { 27736861, 10103576, 12500508, 8502413, -3413016, -9633558, 10436918, -1550276, -23659143, -8132100 }, { 19492550, -12104365, -29681976, -852630, -3208171, 12403437, 30066266, 8367329, 13243957, 8709688 }, }, }, { { { 12015105, 2801261, 28198131, 10151021, 24818120, -4743133, -11194191, -5645734, 5150968, 7274186 }, { 2831366, -12492146, 1478975, 6122054, 23825128, -12733586, 31097299, 6083058, 31021603, -9793610 }, { -2529932, -2229646, 445613, 10720828, -13849527, -11505937, -23507731, 16354465, 15067285, -14147707 }, }, { { 7840942, 14037873, -33364863, 15934016, -728213, -3642706, 21403988, 1057586, -19379462, -12403220 }, { 915865, -16469274, 15608285, -8789130, -24357026, 6060030, -17371319, 8410997, -7220461, 16527025 }, { 32922597, -556987, 20336074, -16184568, 10903705, -5384487, 16957574, 52992, 23834301, 6588044 }, }, { { 32752030, 11232950, 3381995, -8714866, 22652988, -10744103, 17159699, 16689107, -20314580, -1305992 }, { -4689649, 9166776, -25710296, -10847306, 11576752, 12733943, 7924251, -2752281, 1976123, -7249027 }, { 21251222, 16309901, -2983015, -6783122, 30810597, 12967303, 156041, -3371252, 12331345, -8237197 }, }, { { 8651614, -4477032, -16085636, -4996994, 13002507, 2950805, 29054427, -5106970, 10008136, -4667901 }, { 31486080, 15114593, -14261250, 12951354, 14369431, -7387845, 16347321, -13662089, 8684155, -10532952 }, { 19443825, 11385320, 24468943, -9659068, -23919258, 2187569, -26263207, -6086921, 31316348, 14219878 }, }, { { -28594490, 1193785, 32245219, 11392485, 31092169, 15722801, 27146014, 6992409, 29126555, 9207390 }, { 32382935, 1110093, 18477781, 11028262, -27411763, -7548111, -4980517, 10843782, -7957600, -14435730 }, { 2814918, 7836403, 27519878, -7868156, -20894015, -11553689, -21494559, 8550130, 28346258, 1994730 }, }, { { -19578299, 8085545, -14000519, -3948622, 2785838, -16231307, -19516951, 7174894, 22628102, 8115180 }, { -30405132, 955511, -11133838, -15078069, -32447087, -13278079, -25651578, 3317160, -9943017, 930272 }, { -15303681, -6833769, 28856490, 1357446, 23421993, 1057177, 24091212, -1388970, -22765376, -10650715 }, }, { { -22751231, -5303997, -12907607, -12768866, -15811511, -7797053, -14839018, -16554220, -1867018, 8398970 }, { -31969310, 2106403, -4736360, 1362501, 12813763, 16200670, 22981545, -6291273, 18009408, -15772772 }, { -17220923, -9545221, -27784654, 14166835, 29815394, 7444469, 29551787, -3727419, 19288549, 1325865 }, }, { { 15100157, -15835752, -23923978, -1005098, -26450192, 15509408, 12376730, -3479146, 33166107, -8042750 }, { 20909231, 13023121, -9209752, 16251778, -5778415, -8094914, 12412151, 10018715, 2213263, -13878373 }, { 32529814, -11074689, 30361439, -16689753, -9135940, 1513226, 22922121, 6382134, -5766928, 8371348 }, }, }, { { { 9923462, 11271500, 12616794, 3544722, -29998368, -1721626, 12891687, -8193132, -26442943, 10486144 }, { -22597207, -7012665, 8587003, -8257861, 4084309, -12970062, 361726, 2610596, -23921530, -11455195 }, { 5408411, -1136691, -4969122, 10561668, 24145918, 14240566, 31319731, -4235541, 19985175, -3436086 }, }, { { -13994457, 16616821, 14549246, 3341099, 32155958, 13648976, -17577068, 8849297, 65030, 8370684 }, { -8320926, -12049626, 31204563, 5839400, -20627288, -1057277, -19442942, 6922164, 12743482, -9800518 }, { -2361371, 12678785, 28815050, 4759974, -23893047, 4884717, 23783145, 11038569, 18800704, 255233 }, }, { { -5269658, -1773886, 13957886, 7990715, 23132995, 728773, 13393847, 9066957, 19258688, -14753793 }, { -2936654, -10827535, -10432089, 14516793, -3640786, 4372541, -31934921, 2209390, -1524053, 2055794 }, { 580882, 16705327, 5468415, -2683018, -30926419, -14696000, -7203346, -8994389, -30021019, 7394435 }, }, { { 23838809, 1822728, -15738443, 15242727, 8318092, -3733104, -21672180, -3492205, -4821741, 14799921 }, { 13345610, 9759151, 3371034, -16137791, 16353039, 8577942, 31129804, 13496856, -9056018, 7402518 }, { 2286874, -4435931, -20042458, -2008336, -13696227, 5038122, 11006906, -15760352, 8205061, 1607563 }, }, { { 14414086, -8002132, 3331830, -3208217, 22249151, -5594188, 18364661, -2906958, 30019587, -9029278 }, { -27688051, 1585953, -10775053, 931069, -29120221, -11002319, -14410829, 12029093, 9944378, 8024 }, { 4368715, -3709630, 29874200, -15022983, -20230386, -11410704, -16114594, -999085, -8142388, 5640030 }, }, { { 10299610, 13746483, 11661824, 16234854, 7630238, 5998374, 9809887, -16694564, 15219798, -14327783 }, { 27425505, -5719081, 3055006, 10660664, 23458024, 595578, -15398605, -1173195, -18342183, 9742717 }, { 6744077, 2427284, 26042789, 2720740, -847906, 1118974, 32324614, 7406442, 12420155, 1994844 }, }, { { 14012521, -5024720, -18384453, -9578469, -26485342, -3936439, -13033478, -10909803, 24319929, -6446333 }, { 16412690, -4507367, 10772641, 15929391, -17068788, -4658621, 10555945, -10484049, -30102368, -4739048 }, { 22397382, -7767684, -9293161, -12792868, 17166287, -9755136, -27333065, 6199366, 21880021, -12250760 }, }, { { -4283307, 5368523, -31117018, 8163389, -30323063, 3209128, 16557151, 8890729, 8840445, 4957760 }, { -15447727, 709327, -6919446, -10870178, -29777922, 6522332, -21720181, 12130072, -14796503, 5005757 }, { -2114751, -14308128, 23019042, 15765735, -25269683, 6002752, 10183197, -13239326, -16395286, -2176112 }, }, }, { { { -19025756, 1632005, 13466291, -7995100, -23640451, 16573537, -32013908, -3057104, 22208662, 2000468 }, { 3065073, -1412761, -25598674, -361432, -17683065, -5703415, -8164212, 11248527, -3691214, -7414184 }, { 10379208, -6045554, 8877319, 1473647, -29291284, -12507580, 16690915, 2553332, -3132688, 16400289 }, }, { { 15716668, 1254266, -18472690, 7446274, -8448918, 6344164, -22097271, -7285580, 26894937, 9132066 }, { 24158887, 12938817, 11085297, -8177598, -28063478, -4457083, -30576463, 64452, -6817084, -2692882 }, { 13488534, 7794716, 22236231, 5989356, 25426474, -12578208, 2350710, -3418511, -4688006, 2364226 }, }, { { 16335052, 9132434, 25640582, 6678888, 1725628, 8517937, -11807024, -11697457, 15445875, -7798101 }, { 29004207, -7867081, 28661402, -640412, -12794003, -7943086, 31863255, -4135540, -278050, -15759279 }, { -6122061, -14866665, -28614905, 14569919, -10857999, -3591829, 10343412, -6976290, -29828287, -10815811 }, }, { { 27081650, 3463984, 14099042, -4517604, 1616303, -6205604, 29542636, 15372179, 17293797, 960709 }, { 20263915, 11434237, -5765435, 11236810, 13505955, -10857102, -16111345, 6493122, -19384511, 7639714 }, { -2830798, -14839232, 25403038, -8215196, -8317012, -16173699, 18006287, -16043750, 29994677, -15808121 }, }, { { 9769828, 5202651, -24157398, -13631392, -28051003, -11561624, -24613141, -13860782, -31184575, 709464 }, { 12286395, 13076066, -21775189, -1176622, -25003198, 4057652, -32018128, -8890874, 16102007, 13205847 }, { 13733362, 5599946, 10557076, 3195751, -5557991, 8536970, -25540170, 8525972, 10151379, 10394400 }, }, { { 4024660, -16137551, 22436262, 12276534, -9099015, -2686099, 19698229, 11743039, -33302334, 8934414 }, { -15879800, -4525240, -8580747, -2934061, 14634845, -698278, -9449077, 3137094, -11536886, 11721158 }, { 17555939, -5013938, 8268606, 2331751, -22738815, 9761013, 9319229, 8835153, -9205489, -1280045 }, }, { { -461409, -7830014, 20614118, 16688288, -7514766, -4807119, 22300304, 505429, 6108462, -6183415 }, { -5070281, 12367917, -30663534, 3234473, 32617080, -8422642, 29880583, -13483331, -26898490, -7867459 }, { -31975283, 5726539, 26934134, 10237677, -3173717, -605053, 24199304, 3795095, 7592688, -14992079 }, }, { { 21594432, -14964228, 17466408, -4077222, 32537084, 2739898, 6407723, 12018833, -28256052, 4298412 }, { -20650503, -11961496, -27236275, 570498, 3767144, -1717540, 13891942, -1569194, 13717174, 10805743 }, { -14676630, -15644296, 15287174, 11927123, 24177847, -8175568, -796431, 14860609, -26938930, -5863836 }, }, }, { { { 12962541, 5311799, -10060768, 11658280, 18855286, -7954201, 13286263, -12808704, -4381056, 9882022 }, { 18512079, 11319350, -20123124, 15090309, 18818594, 5271736, -22727904, 3666879, -23967430, -3299429 }, { -6789020, -3146043, 16192429, 13241070, 15898607, -14206114, -10084880, -6661110, -2403099, 5276065 }, }, { { 30169808, -5317648, 26306206, -11750859, 27814964, 7069267, 7152851, 3684982, 1449224, 13082861 }, { 10342826, 3098505, 2119311, 193222, 25702612, 12233820, 23697382, 15056736, -21016438, -8202000 }, { -33150110, 3261608, 22745853, 7948688, 19370557, -15177665, -26171976, 6482814, -10300080, -11060101 }, }, { { 32869458, -5408545, 25609743, 15678670, -10687769, -15471071, 26112421, 2521008, -22664288, 6904815 }, { 29506923, 4457497, 3377935, -9796444, -30510046, 12935080, 1561737, 3841096, -29003639, -6657642 }, { 10340844, -6630377, -18656632, -2278430, 12621151, -13339055, 30878497, -11824370, -25584551, 5181966 }, }, { { 25940115, -12658025, 17324188, -10307374, -8671468, 15029094, 24396252, -16450922, -2322852, -12388574 }, { -21765684, 9916823, -1300409, 4079498, -1028346, 11909559, 1782390, 12641087, 20603771, -6561742 }, { -18882287, -11673380, 24849422, 11501709, 13161720, -4768874, 1925523, 11914390, 4662781, 7820689 }, }, { { 12241050, -425982, 8132691, 9393934, 32846760, -1599620, 29749456, 12172924, 16136752, 15264020 }, { -10349955, -14680563, -8211979, 2330220, -17662549, -14545780, 10658213, 6671822, 19012087, 3772772 }, { 3753511, -3421066, 10617074, 2028709, 14841030, -6721664, 28718732, -15762884, 20527771, 12988982 }, }, { { -14822485, -5797269, -3707987, 12689773, -898983, -10914866, -24183046, -10564943, 3299665, -12424953 }, { -16777703, -15253301, -9642417, 4978983, 3308785, 8755439, 6943197, 6461331, -25583147, 8991218 }, { -17226263, 1816362, -1673288, -6086439, 31783888, -8175991, -32948145, 7417950, -30242287, 1507265 }, }, { { 29692663, 6829891, -10498800, 4334896, 20945975, -11906496, -28887608, 8209391, 14606362, -10647073 }, { -3481570, 8707081, 32188102, 5672294, 22096700, 1711240, -33020695, 9761487, 4170404, -2085325 }, { -11587470, 14855945, -4127778, -1531857, -26649089, 15084046, 22186522, 16002000, -14276837, -8400798 }, }, { { -4811456, 13761029, -31703877, -2483919, -3312471, 7869047, -7113572, -9620092, 13240845, 10965870 }, { -7742563, -8256762, -14768334, -13656260, -23232383, 12387166, 4498947, 14147411, 29514390, 4302863 }, { -13413405, -12407859, 20757302, -13801832, 14785143, 8976368, -5061276, -2144373, 17846988, -13971927 }, }, }, { { { -2244452, -754728, -4597030, -1066309, -6247172, 1455299, -21647728, -9214789, -5222701, 12650267 }, { -9906797, -16070310, 21134160, 12198166, -27064575, 708126, 387813, 13770293, -19134326, 10958663 }, { 22470984, 12369526, 23446014, -5441109, -21520802, -9698723, -11772496, -11574455, -25083830, 4271862 }, }, { { -25169565, -10053642, -19909332, 15361595, -5984358, 2159192, 75375, -4278529, -32526221, 8469673 }, { 15854970, 4148314, -8893890, 7259002, 11666551, 13824734, -30531198, 2697372, 24154791, -9460943 }, { 15446137, -15806644, 29759747, 14019369, 30811221, -9610191, -31582008, 12840104, 24913809, 9815020 }, }, { { -4709286, -5614269, -31841498, -12288893, -14443537, 10799414, -9103676, 13438769, 18735128, 9466238 }, { 11933045, 9281483, 5081055, -5183824, -2628162, -4905629, -7727821, -10896103, -22728655, 16199064 }, { 14576810, 379472, -26786533, -8317236, -29426508, -10812974, -102766, 1876699, 30801119, 2164795 }, }, { { 15995086, 3199873, 13672555, 13712240, -19378835, -4647646, -13081610, -15496269, -13492807, 1268052 }, { -10290614, -3659039, -3286592, 10948818, 23037027, 3794475, -3470338, -12600221, -17055369, 3565904 }, { 29210088, -9419337, -5919792, -4952785, 10834811, -13327726, -16512102, -10820713, -27162222, -14030531 }, }, { { -13161890, 15508588, 16663704, -8156150, -28349942, 9019123, -29183421, -3769423, 2244111, -14001979 }, { -5152875, -3800936, -9306475, -6071583, 16243069, 14684434, -25673088, -16180800, 13491506, 4641841 }, { 10813417, 643330, -19188515, -728916, 30292062, -16600078, 27548447, -7721242, 14476989, -12767431 }, }, { { 10292079, 9984945, 6481436, 8279905, -7251514, 7032743, 27282937, -1644259, -27912810, 12651324 }, { -31185513, -813383, 22271204, 11835308, 10201545, 15351028, 17099662, 3988035, 21721536, -3148940 }, { 10202177, -6545839, -31373232, -9574638, -32150642, -8119683, -12906320, 3852694, 13216206, 14842320 }, }, { { -15815640, -10601066, -6538952, -7258995, -6984659, -6581778, -31500847, 13765824, -27434397, 9900184 }, { 14465505, -13833331, -32133984, -14738873, -27443187, 12990492, 33046193, 15796406, -7051866, -8040114 }, { 30924417, -8279620, 6359016, -12816335, 16508377, 9071735, -25488601, 15413635, 9524356, -7018878 }, }, { { 12274201, -13175547, 32627641, -1785326, 6736625, 13267305, 5237659, -5109483, 15663516, 4035784 }, { -2951309, 8903985, 17349946, 601635, -16432815, -4612556, -13732739, -15889334, -22258478, 4659091 }, { -16916263, -4952973, -30393711, -15158821, 20774812, 15897498, 5736189, 15026997, -2178256, -13455585 }, }, }, { { { -8858980, -2219056, 28571666, -10155518, -474467, -10105698, -3801496, 278095, 23440562, -290208 }, { 10226241, -5928702, 15139956, 120818, -14867693, 5218603, 32937275, 11551483, -16571960, -7442864 }, { 17932739, -12437276, -24039557, 10749060, 11316803, 7535897, 22503767, 5561594, -3646624, 3898661 }, }, { { 7749907, -969567, -16339731, -16464, -25018111, 15122143, -1573531, 7152530, 21831162, 1245233 }, { 26958459, -14658026, 4314586, 8346991, -5677764, 11960072, -32589295, -620035, -30402091, -16716212 }, { -12165896, 9166947, 33491384, 13673479, 29787085, 13096535, 6280834, 14587357, -22338025, 13987525 }, }, { { -24349909, 7778775, 21116000, 15572597, -4833266, -5357778, -4300898, -5124639, -7469781, -2858068 }, { 9681908, -6737123, -31951644, 13591838, -6883821, 386950, 31622781, 6439245, -14581012, 4091397 }, { -8426427, 1470727, -28109679, -1596990, 3978627, -5123623, -19622683, 12092163, 29077877, -14741988 }, }, { { 5269168, -6859726, -13230211, -8020715, 25932563, 1763552, -5606110, -5505881, -20017847, 2357889 }, { 32264008, -15407652, -5387735, -1160093, -2091322, -3946900, 23104804, -12869908, 5727338, 189038 }, { 14609123, -8954470, -6000566, -16622781, -14577387, -7743898, -26745169, 10942115, -25888931, -14884697 }, }, { { 20513500, 5557931, -15604613, 7829531, 26413943, -2019404, -21378968, 7471781, 13913677, -5137875 }, { -25574376, 11967826, 29233242, 12948236, -6754465, 4713227, -8940970, 14059180, 12878652, 8511905 }, { -25656801, 3393631, -2955415, -7075526, -2250709, 9366908, -30223418, 6812974, 5568676, -3127656 }, }, { { 11630004, 12144454, 2116339, 13606037, 27378885, 15676917, -17408753, -13504373, -14395196, 8070818 }, { 27117696, -10007378, -31282771, -5570088, 1127282, 12772488, -29845906, 10483306, -11552749, -1028714 }, { 10637467, -5688064, 5674781, 1072708, -26343588, -6982302, -1683975, 9177853, -27493162, 15431203 }, }, { { 20525145, 10892566, -12742472, 12779443, -29493034, 16150075, -28240519, 14943142, -15056790, -7935931 }, { -30024462, 5626926, -551567, -9981087, 753598, 11981191, 25244767, -3239766, -3356550, 9594024 }, { -23752644, 2636870, -5163910, -10103818, 585134, 7877383, 11345683, -6492290, 13352335, -10977084 }, }, { { -1931799, -5407458, 3304649, -12884869, 17015806, -4877091, -29783850, -7752482, -13215537, -319204 }, { 20239939, 6607058, 6203985, 3483793, -18386976, -779229, -20723742, 15077870, -22750759, 14523817 }, { 27406042, -6041657, 27423596, -4497394, 4996214, 10002360, -28842031, -4545494, -30172742, -4805667 }, }, }, { { { 11374242, 12660715, 17861383, -12540833, 10935568, 1099227, -13886076, -9091740, -27727044, 11358504 }, { -12730809, 10311867, 1510375, 10778093, -2119455, -9145702, 32676003, 11149336, -26123651, 4985768 }, { -19096303, 341147, -6197485, -239033, 15756973, -8796662, -983043, 13794114, -19414307, -15621255 }, }, { { 6490081, 11940286, 25495923, -7726360, 8668373, -8751316, 3367603, 6970005, -1691065, -9004790 }, { 1656497, 13457317, 15370807, 6364910, 13605745, 8362338, -19174622, -5475723, -16796596, -5031438 }, { -22273315, -13524424, -64685, -4334223, -18605636, -10921968, -20571065, -7007978, -99853, -10237333 }, }, { { 17747465, 10039260, 19368299, -4050591, -20630635, -16041286, 31992683, -15857976, -29260363, -5511971 }, { 31932027, -4986141, -19612382, 16366580, 22023614, 88450, 11371999, -3744247, 4882242, -10626905 }, { 29796507, 37186, 19818052, 10115756, -11829032, 3352736, 18551198, 3272828, -5190932, -4162409 }, }, { { 12501286, 4044383, -8612957, -13392385, -32430052, 5136599, -19230378, -3529697, 330070, -3659409 }, { 6384877, 2899513, 17807477, 7663917, -2358888, 12363165, 25366522, -8573892, -271295, 12071499 }, { -8365515, -4042521, 25133448, -4517355, -6211027, 2265927, -32769618, 1936675, -5159697, 3829363 }, }, { { 28425966, -5835433, -577090, -4697198, -14217555, 6870930, 7921550, -6567787, 26333140, 14267664 }, { -11067219, 11871231, 27385719, -10559544, -4585914, -11189312, 10004786, -8709488, -21761224, 8930324 }, { -21197785, -16396035, 25654216, -1725397, 12282012, 11008919, 1541940, 4757911, -26491501, -16408940 }, }, { { 13537262, -7759490, -20604840, 10961927, -5922820, -13218065, -13156584, 6217254, -15943699, 13814990 }, { -17422573, 15157790, 18705543, 29619, 24409717, -260476, 27361681, 9257833, -1956526, -1776914 }, { -25045300, -10191966, 15366585, 15166509, -13105086, 8423556, -29171540, 12361135, -18685978, 4578290 }, }, { { 24579768, 3711570, 1342322, -11180126, -27005135, 14124956, -22544529, 14074919, 21964432, 8235257 }, { -6528613, -2411497, 9442966, -5925588, 12025640, -1487420, -2981514, -1669206, 13006806, 2355433 }, { -16304899, -13605259, -6632427, -5142349, 16974359, -10911083, 27202044, 1719366, 1141648, -12796236 }, }, { { -12863944, -13219986, -8318266, -11018091, -6810145, -4843894, 13475066, -3133972, 32674895, 13715045 }, { 11423335, -5468059, 32344216, 8962751, 24989809, 9241752, -13265253, 16086212, -28740881, -15642093 }, { -1409668, 12530728, -6368726, 10847387, 19531186, -14132160, -11709148, 7791794, -27245943, 4383347 }, }, }, { { { -28970898, 5271447, -1266009, -9736989, -12455236, 16732599, -4862407, -4906449, 27193557, 6245191 }, { -15193956, 5362278, -1783893, 2695834, 4960227, 12840725, 23061898, 3260492, 22510453, 8577507 }, { -12632451, 11257346, -32692994, 13548177, -721004, 10879011, 31168030, 13952092, -29571492, -3635906 }, }, { { 3877321, -9572739, 32416692, 5405324, -11004407, -13656635, 3759769, 11935320, 5611860, 8164018 }, { -16275802, 14667797, 15906460, 12155291, -22111149, -9039718, 32003002, -8832289, 5773085, -8422109 }, { -23788118, -8254300, 1950875, 8937633, 18686727, 16459170, -905725, 12376320, 31632953, 190926 }, }, { { -24593607, -16138885, -8423991, 13378746, 14162407, 6901328, -8288749, 4508564, -25341555, -3627528 }, { 8884438, -5884009, 6023974, 10104341, -6881569, -4941533, 18722941, -14786005, -1672488, 827625 }, { -32720583, -16289296, -32503547, 7101210, 13354605, 2659080, -1800575, -14108036, -24878478, 1541286 }, }, { { 2901347, -1117687, 3880376, -10059388, -17620940, -3612781, -21802117, -3567481, 20456845, -1885033 }, { 27019610, 12299467, -13658288, -1603234, -12861660, -4861471, -19540150, -5016058, 29439641, 15138866 }, { 21536104, -6626420, -32447818, -10690208, -22408077, 5175814, -5420040, -16361163, 7779328, 109896 }, }, { { 30279744, 14648750, -8044871, 6425558, 13639621, -743509, 28698390, 12180118, 23177719, -554075 }, { 26572847, 3405927, -31701700, 12890905, -19265668, 5335866, -6493768, 2378492, 4439158, -13279347 }, { -22716706, 3489070, -9225266, -332753, 18875722, -1140095, 14819434, -12731527, -17717757, -5461437 }, }, { { -5056483, 16566551, 15953661, 3767752, -10436499, 15627060, -820954, 2177225, 8550082, -15114165 }, { -18473302, 16596775, -381660, 15663611, 22860960, 15585581, -27844109, -3582739, -23260460, -8428588 }, { -32480551, 15707275, -8205912, -5652081, 29464558, 2713815, -22725137, 15860482, -21902570, 1494193 }, }, { { -19562091, -14087393, -25583872, -9299552, 13127842, 759709, 21923482, 16529112, 8742704, 12967017 }, { -28464899, 1553205, 32536856, -10473729, -24691605, -406174, -8914625, -2933896, -29903758, 15553883 }, { 21877909, 3230008, 9881174, 10539357, -4797115, 2841332, 11543572, 14513274, 19375923, -12647961 }, }, { { 8832269, -14495485, 13253511, 5137575, 5037871, 4078777, 24880818, -6222716, 2862653, 9455043 }, { 29306751, 5123106, 20245049, -14149889, 9592566, 8447059, -2077124, -2990080, 15511449, 4789663 }, { -20679756, 7004547, 8824831, -9434977, -4045704, -3750736, -5754762, 108893, 23513200, 16652362 }, }, }, { { { -33256173, 4144782, -4476029, -6579123, 10770039, -7155542, -6650416, -12936300, -18319198, 10212860 }, { 2756081, 8598110, 7383731, -6859892, 22312759, -1105012, 21179801, 2600940, -9988298, -12506466 }, { -24645692, 13317462, -30449259, -15653928, 21365574, -10869657, 11344424, 864440, -2499677, -16710063 }, }, { { -26432803, 6148329, -17184412, -14474154, 18782929, -275997, -22561534, 211300, 2719757, 4940997 }, { -1323882, 3911313, -6948744, 14759765, -30027150, 7851207, 21690126, 8518463, 26699843, 5276295 }, { -13149873, -6429067, 9396249, 365013, 24703301, -10488939, 1321586, 149635, -15452774, 7159369 }, }, { { 9987780, -3404759, 17507962, 9505530, 9731535, -2165514, 22356009, 8312176, 22477218, -8403385 }, { 18155857, -16504990, 19744716, 9006923, 15154154, -10538976, 24256460, -4864995, -22548173, 9334109 }, { 2986088, -4911893, 10776628, -3473844, 10620590, -7083203, -21413845, 14253545, -22587149, 536906 }, }, { { 4377756, 8115836, 24567078, 15495314, 11625074, 13064599, 7390551, 10589625, 10838060, -15420424 }, { -19342404, 867880, 9277171, -3218459, -14431572, -1986443, 19295826, -15796950, 6378260, 699185 }, { 7895026, 4057113, -7081772, -13077756, -17886831, -323126, -716039, 15693155, -5045064, -13373962 }, }, { { -7737563, -5869402, -14566319, -7406919, 11385654, 13201616, 31730678, -10962840, -3918636, -9669325 }, { 10188286, -15770834, -7336361, 13427543, 22223443, 14896287, 30743455, 7116568, -21786507, 5427593 }, { 696102, 13206899, 27047647, -10632082, 15285305, -9853179, 10798490, -4578720, 19236243, 12477404 }, }, { { -11229439, 11243796, -17054270, -8040865, -788228, -8167967, -3897669, 11180504, -23169516, 7733644 }, { 17800790, -14036179, -27000429, -11766671, 23887827, 3149671, 23466177, -10538171, 10322027, 15313801 }, { 26246234, 11968874, 32263343, -5468728, 6830755, -13323031, -15794704, -101982, -24449242, 10890804 }, }, { { -31365647, 10271363, -12660625, -6267268, 16690207, -13062544, -14982212, 16484931, 25180797, -5334884 }, { -586574, 10376444, -32586414, -11286356, 19801893, 10997610, 2276632, 9482883, 316878, 13820577 }, { -9882808, -4510367, -2115506, 16457136, -11100081, 11674996, 30756178, -7515054, 30696930, -3712849 }, }, { { 32988917, -9603412, 12499366, 7910787, -10617257, -11931514, -7342816, -9985397, -32349517, 7392473 }, { -8855661, 15927861, 9866406, -3649411, -2396914, -16655781, -30409476, -9134995, 25112947, -2926644 }, { -2504044, -436966, 25621774, -5678772, 15085042, -5479877, -24884878, -13526194, 5537438, -13914319 }, }, }, { { { -11225584, 2320285, -9584280, 10149187, -33444663, 5808648, -14876251, -1729667, 31234590, 6090599 }, { -9633316, 116426, 26083934, 2897444, -6364437, -2688086, 609721, 15878753, -6970405, -9034768 }, { -27757857, 247744, -15194774, -9002551, 23288161, -10011936, -23869595, 6503646, 20650474, 1804084 }, }, { { -27589786, 15456424, 8972517, 8469608, 15640622, 4439847, 3121995, -10329713, 27842616, -202328 }, { -15306973, 2839644, 22530074, 10026331, 4602058, 5048462, 28248656, 5031932, -11375082, 12714369 }, { 20807691, -7270825, 29286141, 11421711, -27876523, -13868230, -21227475, 1035546, -19733229, 12796920 }, }, { { 12076899, -14301286, -8785001, -11848922, -25012791, 16400684, -17591495, -12899438, 3480665, -15182815 }, { -32361549, 5457597, 28548107, 7833186, 7303070, -11953545, -24363064, -15921875, -33374054, 2771025 }, { -21389266, 421932, 26597266, 6860826, 22486084, -6737172, -17137485, -4210226, -24552282, 15673397 }, }, { { -20184622, 2338216, 19788685, -9620956, -4001265, -8740893, -20271184, 4733254, 3727144, -12934448 }, { 6120119, 814863, -11794402, -622716, 6812205, -15747771, 2019594, 7975683, 31123697, -10958981 }, { 30069250, -11435332, 30434654, 2958439, 18399564, -976289, 12296869, 9204260, -16432438, 9648165 }, }, { { 32705432, -1550977, 30705658, 7451065, -11805606, 9631813, 3305266, 5248604, -26008332, -11377501 }, { 17219865, 2375039, -31570947, -5575615, -19459679, 9219903, 294711, 15298639, 2662509, -16297073 }, { -1172927, -7558695, -4366770, -4287744, -21346413, -8434326, 32087529, -1222777, 32247248, -14389861 }, }, { { 14312628, 1221556, 17395390, -8700143, -4945741, -8684635, -28197744, -9637817, -16027623, -13378845 }, { -1428825, -9678990, -9235681, 6549687, -7383069, -468664, 23046502, 9803137, 17597934, 2346211 }, { 18510800, 15337574, 26171504, 981392, -22241552, 7827556, -23491134, -11323352, 3059833, -11782870 }, }, { { 10141598, 6082907, 17829293, -1947643, 9830092, 13613136, -25556636, -5544586, -33502212, 3592096 }, { 33114168, -15889352, -26525686, -13343397, 33076705, 8716171, 1151462, 1521897, -982665, -6837803 }, { -32939165, -4255815, 23947181, -324178, -33072974, -12305637, -16637686, 3891704, 26353178, 693168 }, }, { { 30374239, 1595580, -16884039, 13186931, 4600344, 406904, 9585294, -400668, 31375464, 14369965 }, { -14370654, -7772529, 1510301, 6434173, -18784789, -6262728, 32732230, -13108839, 17901441, 16011505 }, { 18171223, -11934626, -12500402, 15197122, -11038147, -15230035, -19172240, -16046376, 8764035, 12309598 }, }, }, { { { 5975908, -5243188, -19459362, -9681747, -11541277, 14015782, -23665757, 1228319, 17544096, -10593782 }, { 5811932, -1715293, 3442887, -2269310, -18367348, -8359541, -18044043, -15410127, -5565381, 12348900 }, { -31399660, 11407555, 25755363, 6891399, -3256938, 14872274, -24849353, 8141295, -10632534, -585479 }, }, { { -12675304, 694026, -5076145, 13300344, 14015258, -14451394, -9698672, -11329050, 30944593, 1130208 }, { 8247766, -6710942, -26562381, -7709309, -14401939, -14648910, 4652152, 2488540, 23550156, -271232 }, { 17294316, -3788438, 7026748, 15626851, 22990044, 113481, 2267737, -5908146, -408818, -137719 }, }, { { 16091085, -16253926, 18599252, 7340678, 2137637, -1221657, -3364161, 14550936, 3260525, -7166271 }, { -4910104, -13332887, 18550887, 10864893, -16459325, -7291596, -23028869, -13204905, -12748722, 2701326 }, { -8574695, 16099415, 4629974, -16340524, -20786213, -6005432, -10018363, 9276971, 11329923, 1862132 }, }, { { 14763076, -15903608, -30918270, 3689867, 3511892, 10313526, -21951088, 12219231, -9037963, -940300 }, { 8894987, -3446094, 6150753, 3013931, 301220, 15693451, -31981216, -2909717, -15438168, 11595570 }, { 15214962, 3537601, -26238722, -14058872, 4418657, -15230761, 13947276, 10730794, -13489462, -4363670 }, }, { { -2538306, 7682793, 32759013, 263109, -29984731, -7955452, -22332124, -10188635, 977108, 699994 }, { -12466472, 4195084, -9211532, 550904, -15565337, 12917920, 19118110, -439841, -30534533, -14337913 }, { 31788461, -14507657, 4799989, 7372237, 8808585, -14747943, 9408237, -10051775, 12493932, -5409317 }, }, { { -25680606, 5260744, -19235809, -6284470, -3695942, 16566087, 27218280, 2607121, 29375955, 6024730 }, { 842132, -2794693, -4763381, -8722815, 26332018, -12405641, 11831880, 6985184, -9940361, 2854096 }, { -4847262, -7969331, 2516242, -5847713, 9695691, -7221186, 16512645, 960770, 12121869, 16648078 }, }, { { -15218652, 14667096, -13336229, 2013717, 30598287, -464137, -31504922, -7882064, 20237806, 2838411 }, { -19288047, 4453152, 15298546, -16178388, 22115043, -15972604, 12544294, -13470457, 1068881, -12499905 }, { -9558883, -16518835, 33238498, 13506958, 30505848, -1114596, -8486907, -2630053, 12521378, 4845654 }, }, { { -28198521, 10744108, -2958380, 10199664, 7759311, -13088600, 3409348, -873400, -6482306, -12885870 }, { -23561822, 6230156, -20382013, 10655314, -24040585, -11621172, 10477734, -1240216, -3113227, 13974498 }, { 12966261, 15550616, -32038948, -1615346, 21025980, -629444, 5642325, 7188737, 18895762, 12629579 }, }, }, { { { 14741879, -14946887, 22177208, -11721237, 1279741, 8058600, 11758140, 789443, 32195181, 3895677 }, { 10758205, 15755439, -4509950, 9243698, -4879422, 6879879, -2204575, -3566119, -8982069, 4429647 }, { -2453894, 15725973, -20436342, -10410672, -5803908, -11040220, -7135870, -11642895, 18047436, -15281743 }, }, { { -25173001, -11307165, 29759956, 11776784, -22262383, -15820455, 10993114, -12850837, -17620701, -9408468 }, { 21987233, 700364, -24505048, 14972008, -7774265, -5718395, 32155026, 2581431, -29958985, 8773375 }, { -25568350, 454463, -13211935, 16126715, 25240068, 8594567, 20656846, 12017935, -7874389, -13920155 }, }, { { 6028182, 6263078, -31011806, -11301710, -818919, 2461772, -31841174, -5468042, -1721788, -2776725 }, { -12278994, 16624277, 987579, -5922598, 32908203, 1248608, 7719845, -4166698, 28408820, 6816612 }, { -10358094, -8237829, 19549651, -12169222, 22082623, 16147817, 20613181, 13982702, -10339570, 5067943 }, }, { { -30505967, -3821767, 12074681, 13582412, -19877972, 2443951, -19719286, 12746132, 5331210, -10105944 }, { 30528811, 3601899, -1957090, 4619785, -27361822, -15436388, 24180793, -12570394, 27679908, -1648928 }, { 9402404, -13957065, 32834043, 10838634, -26580150, -13237195, 26653274, -8685565, 22611444, -12715406 }, }, { { 22190590, 1118029, 22736441, 15130463, -30460692, -5991321, 19189625, -4648942, 4854859, 6622139 }, { -8310738, -2953450, -8262579, -3388049, -10401731, -271929, 13424426, -3567227, 26404409, 13001963 }, { -31241838, -15415700, -2994250, 8939346, 11562230, -12840670, -26064365, -11621720, -15405155, 11020693 }, }, { { 1866042, -7949489, -7898649, -10301010, 12483315, 13477547, 3175636, -12424163, 28761762, 1406734 }, { -448555, -1777666, 13018551, 3194501, -9580420, -11161737, 24760585, -4347088, 25577411, -13378680 }, { -24290378, 4759345, -690653, -1852816, 2066747, 10693769, -29595790, 9884936, -9368926, 4745410 }, }, { { -9141284, 6049714, -19531061, -4341411, -31260798, 9944276, -15462008, -11311852, 10931924, -11931931 }, { -16561513, 14112680, -8012645, 4817318, -8040464, -11414606, -22853429, 10856641, -20470770, 13434654 }, { 22759489, -10073434, -16766264, -1871422, 13637442, -10168091, 1765144, -12654326, 28445307, -5364710 }, }, { { 29875063, 12493613, 2795536, -3786330, 1710620, 15181182, -10195717, -8788675, 9074234, 1167180 }, { -26205683, 11014233, -9842651, -2635485, -26908120, 7532294, -18716888, -9535498, 3843903, 9367684 }, { -10969595, -6403711, 9591134, 9582310, 11349256, 108879, 16235123, 8601684, -139197, 4242895 }, }, }, { { { 22092954, -13191123, -2042793, -11968512, 32186753, -11517388, -6574341, 2470660, -27417366, 16625501 }, { -11057722, 3042016, 13770083, -9257922, 584236, -544855, -7770857, 2602725, -27351616, 14247413 }, { 6314175, -10264892, -32772502, 15957557, -10157730, 168750, -8618807, 14290061, 27108877, -1180880 }, }, { { -8586597, -7170966, 13241782, 10960156, -32991015, -13794596, 33547976, -11058889, -27148451, 981874 }, { 22833440, 9293594, -32649448, -13618667, -9136966, 14756819, -22928859, -13970780, -10479804, -16197962 }, { -7768587, 3326786, -28111797, 10783824, 19178761, 14905060, 22680049, 13906969, -15933690, 3797899 }, }, { { 21721356, -4212746, -12206123, 9310182, -3882239, -13653110, 23740224, -2709232, 20491983, -8042152 }, { 9209270, -15135055, -13256557, -6167798, -731016, 15289673, 25947805, 15286587, 30997318, -6703063 }, { 7392032, 16618386, 23946583, -8039892, -13265164, -1533858, -14197445, -2321576, 17649998, -250080 }, }, { { -9301088, -14193827, 30609526, -3049543, -25175069, -1283752, -15241566, -9525724, -2233253, 7662146 }, { -17558673, 1763594, -33114336, 15908610, -30040870, -12174295, 7335080, -8472199, -3174674, 3440183 }, { -19889700, -5977008, -24111293, -9688870, 10799743, -16571957, 40450, -4431835, 4862400, 1133 }, }, { { -32856209, -7873957, -5422389, 14860950, -16319031, 7956142, 7258061, 311861, -30594991, -7379421 }, { -3773428, -1565936, 28985340, 7499440, 24445838, 9325937, 29727763, 16527196, 18278453, 15405622 }, { -4381906, 8508652, -19898366, -3674424, -5984453, 15149970, -13313598, 843523, -21875062, 13626197 }, }, { { 2281448, -13487055, -10915418, -2609910, 1879358, 16164207, -10783882, 3953792, 13340839, 15928663 }, { 31727126, -7179855, -18437503, -8283652, 2875793, -16390330, -25269894, -7014826, -23452306, 5964753 }, { 4100420, -5959452, -17179337, 6017714, -18705837, 12227141, -26684835, 11344144, 2538215, -7570755 }, }, { { -9433605, 6123113, 11159803, -2156608, 30016280, 14966241, -20474983, 1485421, -629256, -15958862 }, { -26804558, 4260919, 11851389, 9658551, -32017107, 16367492, -20205425, -13191288, 11659922, -11115118 }, { 26180396, 10015009, -30844224, -8581293, 5418197, 9480663, 2231568, -10170080, 33100372, -1306171 }, }, { { 15121113, -5201871, -10389905, 15427821, -27509937, -15992507, 21670947, 4486675, -5931810, -14466380 }, { 16166486, -9483733, -11104130, 6023908, -31926798, -1364923, 2340060, -16254968, -10735770, -10039824 }, { 28042865, -3557089, -12126526, 12259706, -3717498, -6945899, 6766453, -8689599, 18036436, 5803270 }, }, }, { { { -817581, 6763912, 11803561, 1585585, 10958447, -2671165, 23855391, 4598332, -6159431, -14117438 }, { -31031306, -14256194, 17332029, -2383520, 31312682, -5967183, 696309, 50292, -20095739, 11763584 }, { -594563, -2514283, -32234153, 12643980, 12650761, 14811489, 665117, -12613632, -19773211, -10713562 }, }, { { 30464590, -11262872, -4127476, -12734478, 19835327, -7105613, -24396175, 2075773, -17020157, 992471 }, { 18357185, -6994433, 7766382, 16342475, -29324918, 411174, 14578841, 8080033, -11574335, -10601610 }, { 19598397, 10334610, 12555054, 2555664, 18821899, -10339780, 21873263, 16014234, 26224780, 16452269 }, }, { { -30223925, 5145196, 5944548, 16385966, 3976735, 2009897, -11377804, -7618186, -20533829, 3698650 }, { 14187449, 3448569, -10636236, -10810935, -22663880, -3433596, 7268410, -10890444, 27394301, 12015369 }, { 19695761, 16087646, 28032085, 12999827, 6817792, 11427614, 20244189, -1312777, -13259127, -3402461 }, }, { { 30860103, 12735208, -1888245, -4699734, -16974906, 2256940, -8166013, 12298312, -8550524, -10393462 }, { -5719826, -11245325, -1910649, 15569035, 26642876, -7587760, -5789354, -15118654, -4976164, 12651793 }, { -2848395, 9953421, 11531313, -5282879, 26895123, -12697089, -13118820, -16517902, 9768698, -2533218 }, }, { { -24719459, 1894651, -287698, -4704085, 15348719, -8156530, 32767513, 12765450, 4940095, 10678226 }, { 18860224, 15980149, -18987240, -1562570, -26233012, -11071856, -7843882, 13944024, -24372348, 16582019 }, { -15504260, 4970268, -29893044, 4175593, -20993212, -2199756, -11704054, 15444560, -11003761, 7989037 }, }, { { 31490452, 5568061, -2412803, 2182383, -32336847, 4531686, -32078269, 6200206, -19686113, -14800171 }, { -17308668, -15879940, -31522777, -2831, -32887382, 16375549, 8680158, -16371713, 28550068, -6857132 }, { -28126887, -5688091, 16837845, -1820458, -6850681, 12700016, -30039981, 4364038, 1155602, 5988841 }, }, { { 21890435, -13272907, -12624011, 12154349, -7831873, 15300496, 23148983, -4470481, 24618407, 8283181 }, { -33136107, -10512751, 9975416, 6841041, -31559793, 16356536, 3070187, -7025928, 1466169, 10740210 }, { -1509399, -15488185, -13503385, -10655916, 32799044, 909394, -13938903, -5779719, -32164649, -15327040 }, }, { { 3960823, -14267803, -28026090, -15918051, -19404858, 13146868, 15567327, 951507, -3260321, -573935 }, { 24740841, 5052253, -30094131, 8961361, 25877428, 6165135, -24368180, 14397372, -7380369, -6144105 }, { -28888365, 3510803, -28103278, -1158478, -11238128, -10631454, -15441463, -14453128, -1625486, -6494814 }, }, }, { { { 793299, -9230478, 8836302, -6235707, -27360908, -2369593, 33152843, -4885251, -9906200, -621852 }, { 5666233, 525582, 20782575, -8038419, -24538499, 14657740, 16099374, 1468826, -6171428, -15186581 }, { -4859255, -3779343, -2917758, -6748019, 7778750, 11688288, -30404353, -9871238, -1558923, -9863646 }, }, { { 10896332, -7719704, 824275, 472601, -19460308, 3009587, 25248958, 14783338, -30581476, -15757844 }, { 10566929, 12612572, -31944212, 11118703, -12633376, 12362879, 21752402, 8822496, 24003793, 14264025 }, { 27713862, -7355973, -11008240, 9227530, 27050101, 2504721, 23886875, -13117525, 13958495, -5732453 }, }, { { -23481610, 4867226, -27247128, 3900521, 29838369, -8212291, -31889399, -10041781, 7340521, -15410068 }, { 4646514, -8011124, -22766023, -11532654, 23184553, 8566613, 31366726, -1381061, -15066784, -10375192 }, { -17270517, 12723032, -16993061, 14878794, 21619651, -6197576, 27584817, 3093888, -8843694, 3849921 }, }, { { -9064912, 2103172, 25561640, -15125738, -5239824, 9582958, 32477045, -9017955, 5002294, -15550259 }, { -12057553, -11177906, 21115585, -13365155, 8808712, -12030708, 16489530, 13378448, -25845716, 12741426 }, { -5946367, 10645103, -30911586, 15390284, -3286982, -7118677, 24306472, 15852464, 28834118, -7646072 }, }, { { -17335748, -9107057, -24531279, 9434953, -8472084, -583362, -13090771, 455841, 20461858, 5491305 }, { 13669248, -16095482, -12481974, -10203039, -14569770, -11893198, -24995986, 11293807, -28588204, -9421832 }, { 28497928, 6272777, -33022994, 14470570, 8906179, -1225630, 18504674, -14165166, 29867745, -8795943 }, }, { { -16207023, 13517196, -27799630, -13697798, 24009064, -6373891, -6367600, -13175392, 22853429, -4012011 }, { 24191378, 16712145, -13931797, 15217831, 14542237, 1646131, 18603514, -11037887, 12876623, -2112447 }, { 17902668, 4518229, -411702, -2829247, 26878217, 5258055, -12860753, 608397, 16031844, 3723494 }, }, { { -28632773, 12763728, -20446446, 7577504, 33001348, -13017745, 17558842, -7872890, 23896954, -4314245 }, { -20005381, -12011952, 31520464, 605201, 2543521, 5991821, -2945064, 7229064, -9919646, -8826859 }, { 28816045, 298879, -28165016, -15920938, 19000928, -1665890, -12680833, -2949325, -18051778, -2082915 }, }, { { 16000882, -344896, 3493092, -11447198, -29504595, -13159789, 12577740, 16041268, -19715240, 7847707 }, { 10151868, 10572098, 27312476, 7922682, 14825339, 4723128, -32855931, -6519018, -10020567, 3852848 }, { -11430470, 15697596, -21121557, -4420647, 5386314, 15063598, 16514493, -15932110, 29330899, -15076224 }, }, }, { { { -25499735, -4378794, -15222908, -6901211, 16615731, 2051784, 3303702, 15490, -27548796, 12314391 }, { 15683520, -6003043, 18109120, -9980648, 15337968, -5997823, -16717435, 15921866, 16103996, -3731215 }, { -23169824, -10781249, 13588192, -1628807, -3798557, -1074929, -19273607, 5402699, -29815713, -9841101 }, }, { { 23190676, 2384583, -32714340, 3462154, -29903655, -1529132, -11266856, 8911517, -25205859, 2739713 }, { 21374101, -3554250, -33524649, 9874411, 15377179, 11831242, -33529904, 6134907, 4931255, 11987849 }, { -7732, -2978858, -16223486, 7277597, 105524, -322051, -31480539, 13861388, -30076310, 10117930 }, }, { { -29501170, -10744872, -26163768, 13051539, -25625564, 5089643, -6325503, 6704079, 12890019, 15728940 }, { -21972360, -11771379, -951059, -4418840, 14704840, 2695116, 903376, -10428139, 12885167, 8311031 }, { -17516482, 5352194, 10384213, -13811658, 7506451, 13453191, 26423267, 4384730, 1888765, -5435404 }, }, { { -25817338, -3107312, -13494599, -3182506, 30896459, -13921729, -32251644, -12707869, -19464434, -3340243 }, { -23607977, -2665774, -526091, 4651136, 5765089, 4618330, 6092245, 14845197, 17151279, -9854116 }, { -24830458, -12733720, -15165978, 10367250, -29530908, -265356, 22825805, -7087279, -16866484, 16176525 }, }, { { -23583256, 6564961, 20063689, 3798228, -4740178, 7359225, 2006182, -10363426, -28746253, -10197509 }, { -10626600, -4486402, -13320562, -5125317, 3432136, -6393229, 23632037, -1940610, 32808310, 1099883 }, { 15030977, 5768825, -27451236, -2887299, -6427378, -15361371, -15277896, -6809350, 2051441, -15225865 }, }, { { -3362323, -7239372, 7517890, 9824992, 23555850, 295369, 5148398, -14154188, -22686354, 16633660 }, { 4577086, -16752288, 13249841, -15304328, 19958763, -14537274, 18559670, -10759549, 8402478, -9864273 }, { -28406330, -1051581, -26790155, -907698, -17212414, -11030789, 9453451, -14980072, 17983010, 9967138 }, }, { { -25762494, 6524722, 26585488, 9969270, 24709298, 1220360, -1677990, 7806337, 17507396, 3651560 }, { -10420457, -4118111, 14584639, 15971087, -15768321, 8861010, 26556809, -5574557, -18553322, -11357135 }, { 2839101, 14284142, 4029895, 3472686, 14402957, 12689363, -26642121, 8459447, -5605463, -7621941 }, }, { { -4839289, -3535444, 9744961, 2871048, 25113978, 3187018, -25110813, -849066, 17258084, -7977739 }, { 18164541, -10595176, -17154882, -1542417, 19237078, -9745295, 23357533, -15217008, 26908270, 12150756 }, { -30264870, -7647865, 5112249, -7036672, -1499807, -6974257, 43168, -5537701, -32302074, 16215819 }, }, }, { { { -6898905, 9824394, -12304779, -4401089, -31397141, -6276835, 32574489, 12532905, -7503072, -8675347 }, { -27343522, -16515468, -27151524, -10722951, 946346, 16291093, 254968, 7168080, 21676107, -1943028 }, { 21260961, -8424752, -16831886, -11920822, -23677961, 3968121, -3651949, -6215466, -3556191, -7913075 }, }, { { 16544754, 13250366, -16804428, 15546242, -4583003, 12757258, -2462308, -8680336, -18907032, -9662799 }, { -2415239, -15577728, 18312303, 4964443, -15272530, -12653564, 26820651, 16690659, 25459437, -4564609 }, { -25144690, 11425020, 28423002, -11020557, -6144921, -15826224, 9142795, -2391602, -6432418, -1644817 }, }, { { -23104652, 6253476, 16964147, -3768872, -25113972, -12296437, -27457225, -16344658, 6335692, 7249989 }, { -30333227, 13979675, 7503222, -12368314, -11956721, -4621693, -30272269, 2682242, 25993170, -12478523 }, { 4364628, 5930691, 32304656, -10044554, -8054781, 15091131, 22857016, -10598955, 31820368, 15075278 }, }, { { 31879134, -8918693, 17258761, 90626, -8041836, -4917709, 24162788, -9650886, -17970238, 12833045 }, { 19073683, 14851414, -24403169, -11860168, 7625278, 11091125, -19619190, 2074449, -9413939, 14905377 }, { 24483667, -11935567, -2518866, -11547418, -1553130, 15355506, -25282080, 9253129, 27628530, -7555480 }, }, { { 17597607, 8340603, 19355617, 552187, 26198470, -3176583, 4593324, -9157582, -14110875, 15297016 }, { 510886, 14337390, -31785257, 16638632, 6328095, 2713355, -20217417, -11864220, 8683221, 2921426 }, { 18606791, 11874196, 27155355, -5281482, -24031742, 6265446, -25178240, -1278924, 4674690, 13890525 }, }, { { 13609624, 13069022, -27372361, -13055908, 24360586, 9592974, 14977157, 9835105, 4389687, 288396 }, { 9922506, -519394, 13613107, 5883594, -18758345, -434263, -12304062, 8317628, 23388070, 16052080 }, { 12720016, 11937594, -31970060, -5028689, 26900120, 8561328, -20155687, -11632979, -14754271, -10812892 }, }, { { 15961858, 14150409, 26716931, -665832, -22794328, 13603569, 11829573, 7467844, -28822128, 929275 }, { 11038231, -11582396, -27310482, -7316562, -10498527, -16307831, -23479533, -9371869, -21393143, 2465074 }, { 20017163, -4323226, 27915242, 1529148, 12396362, 15675764, 13817261, -9658066, 2463391, -4622140 }, }, { { -16358878, -12663911, -12065183, 4996454, -1256422, 1073572, 9583558, 12851107, 4003896, 12673717 }, { -1731589, -15155870, -3262930, 16143082, 19294135, 13385325, 14741514, -9103726, 7903886, 2348101 }, { 24536016, -16515207, 12715592, -3862155, 1511293, 10047386, -3842346, -7129159, -28377538, 10048127 }, }, }, { { { -12622226, -6204820, 30718825, 2591312, -10617028, 12192840, 18873298, -7297090, -32297756, 15221632 }, { -26478122, -11103864, 11546244, -1852483, 9180880, 7656409, -21343950, 2095755, 29769758, 6593415 }, { -31994208, -2907461, 4176912, 3264766, 12538965, -868111, 26312345, -6118678, 30958054, 8292160 }, }, { { 31429822, -13959116, 29173532, 15632448, 12174511, -2760094, 32808831, 3977186, 26143136, -3148876 }, { 22648901, 1402143, -22799984, 13746059, 7936347, 365344, -8668633, -1674433, -3758243, -2304625 }, { -15491917, 8012313, -2514730, -12702462, -23965846, -10254029, -1612713, -1535569, -16664475, 8194478 }, }, { { 27338066, -7507420, -7414224, 10140405, -19026427, -6589889, 27277191, 8855376, 28572286, 3005164 }, { 26287124, 4821776, 25476601, -4145903, -3764513, -15788984, -18008582, 1182479, -26094821, -13079595 }, { -7171154, 3178080, 23970071, 6201893, -17195577, -4489192, -21876275, -13982627, 32208683, -1198248 }, }, { { -16657702, 2817643, -10286362, 14811298, 6024667, 13349505, -27315504, -10497842, -27672585, -11539858 }, { 15941029, -9405932, -21367050, 8062055, 31876073, -238629, -15278393, -1444429, 15397331, -4130193 }, { 8934485, -13485467, -23286397, -13423241, -32446090, 14047986, 31170398, -1441021, -27505566, 15087184 }, }, { { -18357243, -2156491, 24524913, -16677868, 15520427, -6360776, -15502406, 11461896, 16788528, -5868942 }, { -1947386, 16013773, 21750665, 3714552, -17401782, -16055433, -3770287, -10323320, 31322514, -11615635 }, { 21426655, -5650218, -13648287, -5347537, -28812189, -4920970, -18275391, -14621414, 13040862, -12112948 }, }, { { 11293895, 12478086, -27136401, 15083750, -29307421, 14748872, 14555558, -13417103, 1613711, 4896935 }, { -25894883, 15323294, -8489791, -8057900, 25967126, -13425460, 2825960, -4897045, -23971776, -11267415 }, { -15924766, -5229880, -17443532, 6410664, 3622847, 10243618, 20615400, 12405433, -23753030, -8436416 }, }, { { -7091295, 12556208, -20191352, 9025187, -17072479, 4333801, 4378436, 2432030, 23097949, -566018 }, { 4565804, -16025654, 20084412, -7842817, 1724999, 189254, 24767264, 10103221, -18512313, 2424778 }, { 366633, -11976806, 8173090, -6890119, 30788634, 5745705, -7168678, 1344109, -3642553, 12412659 }, }, { { -24001791, 7690286, 14929416, -168257, -32210835, -13412986, 24162697, -15326504, -3141501, 11179385 }, { 18289522, -14724954, 8056945, 16430056, -21729724, 7842514, -6001441, -1486897, -18684645, -11443503 }, { 476239, 6601091, -6152790, -9723375, 17503545, -4863900, 27672959, 13403813, 11052904, 5219329 }, }, }, { { { 20678546, -8375738, -32671898, 8849123, -5009758, 14574752, 31186971, -3973730, 9014762, -8579056 }, { -13644050, -10350239, -15962508, 5075808, -1514661, -11534600, -33102500, 9160280, 8473550, -3256838 }, { 24900749, 14435722, 17209120, -15292541, -22592275, 9878983, -7689309, -16335821, -24568481, 11788948 }, }, { { -3118155, -11395194, -13802089, 14797441, 9652448, -6845904, -20037437, 10410733, -24568470, -1458691 }, { -15659161, 16736706, -22467150, 10215878, -9097177, 7563911, 11871841, -12505194, -18513325, 8464118 }, { -23400612, 8348507, -14585951, -861714, -3950205, -6373419, 14325289, 8628612, 33313881, -8370517 }, }, { { -20186973, -4967935, 22367356, 5271547, -1097117, -4788838, -24805667, -10236854, -8940735, -5818269 }, { -6948785, -1795212, -32625683, -16021179, 32635414, -7374245, 15989197, -12838188, 28358192, -4253904 }, { -23561781, -2799059, -32351682, -1661963, -9147719, 10429267, -16637684, 4072016, -5351664, 5596589 }, }, { { -28236598, -3390048, 12312896, 6213178, 3117142, 16078565, 29266239, 2557221, 1768301, 15373193 }, { -7243358, -3246960, -4593467, -7553353, -127927, -912245, -1090902, -4504991, -24660491, 3442910 }, { -30210571, 5124043, 14181784, 8197961, 18964734, -11939093, 22597931, 7176455, -18585478, 13365930 }, }, { { -7877390, -1499958, 8324673, 4690079, 6261860, 890446, 24538107, -8570186, -9689599, -3031667 }, { 25008904, -10771599, -4305031, -9638010, 16265036, 15721635, 683793, -11823784, 15723479, -15163481 }, { -9660625, 12374379, -27006999, -7026148, -7724114, -12314514, 11879682, 5400171, 519526, -1235876 }, }, { { 22258397, -16332233, -7869817, 14613016, -22520255, -2950923, -20353881, 7315967, 16648397, 7605640 }, { -8081308, -8464597, -8223311, 9719710, 19259459, -15348212, 23994942, -5281555, -9468848, 4763278 }, { -21699244, 9220969, -15730624, 1084137, -25476107, -2852390, 31088447, -7764523, -11356529, 728112 }, }, { { 26047220, -11751471, -6900323, -16521798, 24092068, 9158119, -4273545, -12555558, -29365436, -5498272 }, { 17510331, -322857, 5854289, 8403524, 17133918, -3112612, -28111007, 12327945, 10750447, 10014012 }, { -10312768, 3936952, 9156313, -8897683, 16498692, -994647, -27481051, -666732, 3424691, 7540221 }, }, { { 30322361, -6964110, 11361005, -4143317, 7433304, 4989748, -7071422, -16317219, -9244265, 15258046 }, { 13054562, -2779497, 19155474, 469045, -12482797, 4566042, 5631406, 2711395, 1062915, -5136345 }, { -19240248, -11254599, -29509029, -7499965, -5835763, 13005411, -6066489, 12194497, 32960380, 1459310 }, }, }, { { { 19852034, 7027924, 23669353, 10020366, 8586503, -6657907, 394197, -6101885, 18638003, -11174937 }, { 31395534, 15098109, 26581030, 8030562, -16527914, -5007134, 9012486, -7584354, -6643087, -5442636 }, { -9192165, -2347377, -1997099, 4529534, 25766844, 607986, -13222, 9677543, -32294889, -6456008 }, }, { { -2444496, -149937, 29348902, 8186665, 1873760, 12489863, -30934579, -7839692, -7852844, -8138429 }, { -15236356, -15433509, 7766470, 746860, 26346930, -10221762, -27333451, 10754588, -9431476, 5203576 }, { 31834314, 14135496, -770007, 5159118, 20917671, -16768096, -7467973, -7337524, 31809243, 7347066 }, }, { { -9606723, -11874240, 20414459, 13033986, 13716524, -11691881, 19797970, -12211255, 15192876, -2087490 }, { -12663563, -2181719, 1168162, -3804809, 26747877, -14138091, 10609330, 12694420, 33473243, -13382104 }, { 33184999, 11180355, 15832085, -11385430, -1633671, 225884, 15089336, -11023903, -6135662, 14480053 }, }, { { 31308717, -5619998, 31030840, -1897099, 15674547, -6582883, 5496208, 13685227, 27595050, 8737275 }, { -20318852, -15150239, 10933843, -16178022, 8335352, -7546022, -31008351, -12610604, 26498114, 66511 }, { 22644454, -8761729, -16671776, 4884562, -3105614, -13559366, 30540766, -4286747, -13327787, -7515095 }, }, { { -28017847, 9834845, 18617207, -2681312, -3401956, -13307506, 8205540, 13585437, -17127465, 15115439 }, { 23711543, -672915, 31206561, -8362711, 6164647, -9709987, -33535882, -1426096, 8236921, 16492939 }, { -23910559, -13515526, -26299483, -4503841, 25005590, -7687270, 19574902, 10071562, 6708380, -6222424 }, }, { { 2101391, -4930054, 19702731, 2367575, -15427167, 1047675, 5301017, 9328700, 29955601, -11678310 }, { 3096359, 9271816, -21620864, -15521844, -14847996, -7592937, -25892142, -12635595, -9917575, 6216608 }, { -32615849, 338663, -25195611, 2510422, -29213566, -13820213, 24822830, -6146567, -26767480, 7525079 }, }, { { -23066649, -13985623, 16133487, -7896178, -3389565, 778788, -910336, -2782495, -19386633, 11994101 }, { 21691500, -13624626, -641331, -14367021, 3285881, -3483596, -25064666, 9718258, -7477437, 13381418 }, { 18445390, -4202236, 14979846, 11622458, -1727110, -3582980, 23111648, -6375247, 28535282, 15779576 }, }, { { 30098053, 3089662, -9234387, 16662135, -21306940, 11308411, -14068454, 12021730, 9955285, -16303356 }, { 9734894, -14576830, -7473633, -9138735, 2060392, 11313496, -18426029, 9924399, 20194861, 13380996 }, { -26378102, -7965207, -22167821, 15789297, -18055342, -6168792, -1984914, 15707771, 26342023, 10146099 }, }, }, { { { -26016874, -219943, 21339191, -41388, 19745256, -2878700, -29637280, 2227040, 21612326, -545728 }, { -13077387, 1184228, 23562814, -5970442, -20351244, -6348714, 25764461, 12243797, -20856566, 11649658 }, { -10031494, 11262626, 27384172, 2271902, 26947504, -15997771, 39944, 6114064, 33514190, 2333242 }, }, { { -21433588, -12421821, 8119782, 7219913, -21830522, -9016134, -6679750, -12670638, 24350578, -13450001 }, { -4116307, -11271533, -23886186, 4843615, -30088339, 690623, -31536088, -10406836, 8317860, 12352766 }, { 18200138, -14475911, -33087759, -2696619, -23702521, -9102511, -23552096, -2287550, 20712163, 6719373 }, }, { { 26656208, 6075253, -7858556, 1886072, -28344043, 4262326, 11117530, -3763210, 26224235, -3297458 }, { -17168938, -14854097, -3395676, -16369877, -19954045, 14050420, 21728352, 9493610, 18620611, -16428628 }, { -13323321, 13325349, 11432106, 5964811, 18609221, 6062965, -5269471, -9725556, -30701573, -16479657 }, }, { { -23860538, -11233159, 26961357, 1640861, -32413112, -16737940, 12248509, -5240639, 13735342, 1934062 }, { 25089769, 6742589, 17081145, -13406266, 21909293, -16067981, -15136294, -3765346, -21277997, 5473616 }, { 31883677, -7961101, 1083432, -11572403, 22828471, 13290673, -7125085, 12469656, 29111212, -5451014 }, }, { { 24244947, -15050407, -26262976, 2791540, -14997599, 16666678, 24367466, 6388839, -10295587, 452383 }, { -25640782, -3417841, 5217916, 16224624, 19987036, -4082269, -24236251, -5915248, 15766062, 8407814 }, { -20406999, 13990231, 15495425, 16395525, 5377168, 15166495, -8917023, -4388953, -8067909, 2276718 }, }, { { 30157918, 12924066, -17712050, 9245753, 19895028, 3368142, -23827587, 5096219, 22740376, -7303417 }, { 2041139, -14256350, 7783687, 13876377, -25946985, -13352459, 24051124, 13742383, -15637599, 13295222 }, { 33338237, -8505733, 12532113, 7977527, 9106186, -1715251, -17720195, -4612972, -4451357, -14669444 }, }, { { -20045281, 5454097, -14346548, 6447146, 28862071, 1883651, -2469266, -4141880, 7770569, 9620597 }, { 23208068, 7979712, 33071466, 8149229, 1758231, -10834995, 30945528, -1694323, -33502340, -14767970 }, { 1439958, -16270480, -1079989, -793782, 4625402, 10647766, -5043801, 1220118, 30494170, -11440799 }, }, { { -5037580, -13028295, -2970559, -3061767, 15640974, -6701666, -26739026, 926050, -1684339, -13333647 }, { 13908495, -3549272, 30919928, -6273825, -21521863, 7989039, 9021034, 9078865, 3353509, 4033511 }, { -29663431, -15113610, 32259991, -344482, 24295849, -12912123, 23161163, 8839127, 27485041, 7356032 }, }, }, { { { 9661027, 705443, 11980065, -5370154, -1628543, 14661173, -6346142, 2625015, 28431036, -16771834 }, { -23839233, -8311415, -25945511, 7480958, -17681669, -8354183, -22545972, 14150565, 15970762, 4099461 }, { 29262576, 16756590, 26350592, -8793563, 8529671, -11208050, 13617293, -9937143, 11465739, 8317062 }, }, { { -25493081, -6962928, 32500200, -9419051, -23038724, -2302222, 14898637, 3848455, 20969334, -5157516 }, { -20384450, -14347713, -18336405, 13884722, -33039454, 2842114, -21610826, -3649888, 11177095, 14989547 }, { -24496721, -11716016, 16959896, 2278463, 12066309, 10137771, 13515641, 2581286, -28487508, 9930240 }, }, { { -17751622, -2097826, 16544300, -13009300, -15914807, -14949081, 18345767, -13403753, 16291481, -5314038 }, { -33229194, 2553288, 32678213, 9875984, 8534129, 6889387, -9676774, 6957617, 4368891, 9788741 }, { 16660756, 7281060, -10830758, 12911820, 20108584, -8101676, -21722536, -8613148, 16250552, -11111103 }, }, { { -19765507, 2390526, -16551031, 14161980, 1905286, 6414907, 4689584, 10604807, -30190403, 4782747 }, { -1354539, 14736941, -7367442, -13292886, 7710542, -14155590, -9981571, 4383045, 22546403, 437323 }, { 31665577, -12180464, -16186830, 1491339, -18368625, 3294682, 27343084, 2786261, -30633590, -14097016 }, }, { { -14467279, -683715, -33374107, 7448552, 19294360, 14334329, -19690631, 2355319, -19284671, -6114373 }, { 15121312, -15796162, 6377020, -6031361, -10798111, -12957845, 18952177, 15496498, -29380133, 11754228 }, { -2637277, -13483075, 8488727, -14303896, 12728761, -1622493, 7141596, 11724556, 22761615, -10134141 }, }, { { 16918416, 11729663, -18083579, 3022987, -31015732, -13339659, -28741185, -12227393, 32851222, 11717399 }, { 11166634, 7338049, -6722523, 4531520, -29468672, -7302055, 31474879, 3483633, -1193175, -4030831 }, { -185635, 9921305, 31456609, -13536438, -12013818, 13348923, 33142652, 6546660, -19985279, -3948376 }, }, { { -32460596, 11266712, -11197107, -7899103, 31703694, 3855903, -8537131, -12833048, -30772034, -15486313 }, { -18006477, 12709068, 3991746, -6479188, -21491523, -10550425, -31135347, -16049879, 10928917, 3011958 }, { -6957757, -15594337, 31696059, 334240, 29576716, 14796075, -30831056, -12805180, 18008031, 10258577 }, }, { { -22448644, 15655569, 7018479, -4410003, -30314266, -1201591, -1853465, 1367120, 25127874, 6671743 }, { 29701166, -14373934, -10878120, 9279288, -17568, 13127210, 21382910, 11042292, 25838796, 4642684 }, { -20430234, 14955537, -24126347, 8124619, -5369288, -5990470, 30468147, -13900640, 18423289, 4177476 }, }, }, }; opengnb-ver1.6.0.a/libs/ed25519/sc.c000066400000000000000000000545231500454252100166110ustar00rootroot00000000000000#include "fixedint.h" #include "sc.h" static uint64_t load_3(const unsigned char *in) { uint64_t result; result = (uint64_t) in[0]; result |= ((uint64_t) in[1]) << 8; result |= ((uint64_t) in[2]) << 16; return result; } static uint64_t load_4(const unsigned char *in) { uint64_t result; result = (uint64_t) in[0]; result |= ((uint64_t) in[1]) << 8; result |= ((uint64_t) in[2]) << 16; result |= ((uint64_t) in[3]) << 24; return result; } /* Input: s[0]+256*s[1]+...+256^63*s[63] = s Output: s[0]+256*s[1]+...+256^31*s[31] = s mod l where l = 2^252 + 27742317777372353535851937790883648493. Overwrites s in place. */ void sc_reduce(unsigned char *s) { int64_t s0 = 2097151 & load_3(s); int64_t s1 = 2097151 & (load_4(s + 2) >> 5); int64_t s2 = 2097151 & (load_3(s + 5) >> 2); int64_t s3 = 2097151 & (load_4(s + 7) >> 7); int64_t s4 = 2097151 & (load_4(s + 10) >> 4); int64_t s5 = 2097151 & (load_3(s + 13) >> 1); int64_t s6 = 2097151 & (load_4(s + 15) >> 6); int64_t s7 = 2097151 & (load_3(s + 18) >> 3); int64_t s8 = 2097151 & load_3(s + 21); int64_t s9 = 2097151 & (load_4(s + 23) >> 5); int64_t s10 = 2097151 & (load_3(s + 26) >> 2); int64_t s11 = 2097151 & (load_4(s + 28) >> 7); int64_t s12 = 2097151 & (load_4(s + 31) >> 4); int64_t s13 = 2097151 & (load_3(s + 34) >> 1); int64_t s14 = 2097151 & (load_4(s + 36) >> 6); int64_t s15 = 2097151 & (load_3(s + 39) >> 3); int64_t s16 = 2097151 & load_3(s + 42); int64_t s17 = 2097151 & (load_4(s + 44) >> 5); int64_t s18 = 2097151 & (load_3(s + 47) >> 2); int64_t s19 = 2097151 & (load_4(s + 49) >> 7); int64_t s20 = 2097151 & (load_4(s + 52) >> 4); int64_t s21 = 2097151 & (load_3(s + 55) >> 1); int64_t s22 = 2097151 & (load_4(s + 57) >> 6); int64_t s23 = (load_4(s + 60) >> 3); int64_t carry0; int64_t carry1; int64_t carry2; int64_t carry3; int64_t carry4; int64_t carry5; int64_t carry6; int64_t carry7; int64_t carry8; int64_t carry9; int64_t carry10; int64_t carry11; int64_t carry12; int64_t carry13; int64_t carry14; int64_t carry15; int64_t carry16; s11 += s23 * 666643; s12 += s23 * 470296; s13 += s23 * 654183; s14 -= s23 * 997805; s15 += s23 * 136657; s16 -= s23 * 683901; s23 = 0; s10 += s22 * 666643; s11 += s22 * 470296; s12 += s22 * 654183; s13 -= s22 * 997805; s14 += s22 * 136657; s15 -= s22 * 683901; s22 = 0; s9 += s21 * 666643; s10 += s21 * 470296; s11 += s21 * 654183; s12 -= s21 * 997805; s13 += s21 * 136657; s14 -= s21 * 683901; s21 = 0; s8 += s20 * 666643; s9 += s20 * 470296; s10 += s20 * 654183; s11 -= s20 * 997805; s12 += s20 * 136657; s13 -= s20 * 683901; s20 = 0; s7 += s19 * 666643; s8 += s19 * 470296; s9 += s19 * 654183; s10 -= s19 * 997805; s11 += s19 * 136657; s12 -= s19 * 683901; s19 = 0; s6 += s18 * 666643; s7 += s18 * 470296; s8 += s18 * 654183; s9 -= s18 * 997805; s10 += s18 * 136657; s11 -= s18 * 683901; s18 = 0; carry6 = (s6 + (1 << 20)) >> 21; s7 += carry6; s6 -= carry6 << 21; carry8 = (s8 + (1 << 20)) >> 21; s9 += carry8; s8 -= carry8 << 21; carry10 = (s10 + (1 << 20)) >> 21; s11 += carry10; s10 -= carry10 << 21; carry12 = (s12 + (1 << 20)) >> 21; s13 += carry12; s12 -= carry12 << 21; carry14 = (s14 + (1 << 20)) >> 21; s15 += carry14; s14 -= carry14 << 21; carry16 = (s16 + (1 << 20)) >> 21; s17 += carry16; s16 -= carry16 << 21; carry7 = (s7 + (1 << 20)) >> 21; s8 += carry7; s7 -= carry7 << 21; carry9 = (s9 + (1 << 20)) >> 21; s10 += carry9; s9 -= carry9 << 21; carry11 = (s11 + (1 << 20)) >> 21; s12 += carry11; s11 -= carry11 << 21; carry13 = (s13 + (1 << 20)) >> 21; s14 += carry13; s13 -= carry13 << 21; carry15 = (s15 + (1 << 20)) >> 21; s16 += carry15; s15 -= carry15 << 21; s5 += s17 * 666643; s6 += s17 * 470296; s7 += s17 * 654183; s8 -= s17 * 997805; s9 += s17 * 136657; s10 -= s17 * 683901; s17 = 0; s4 += s16 * 666643; s5 += s16 * 470296; s6 += s16 * 654183; s7 -= s16 * 997805; s8 += s16 * 136657; s9 -= s16 * 683901; s16 = 0; s3 += s15 * 666643; s4 += s15 * 470296; s5 += s15 * 654183; s6 -= s15 * 997805; s7 += s15 * 136657; s8 -= s15 * 683901; s15 = 0; s2 += s14 * 666643; s3 += s14 * 470296; s4 += s14 * 654183; s5 -= s14 * 997805; s6 += s14 * 136657; s7 -= s14 * 683901; s14 = 0; s1 += s13 * 666643; s2 += s13 * 470296; s3 += s13 * 654183; s4 -= s13 * 997805; s5 += s13 * 136657; s6 -= s13 * 683901; s13 = 0; s0 += s12 * 666643; s1 += s12 * 470296; s2 += s12 * 654183; s3 -= s12 * 997805; s4 += s12 * 136657; s5 -= s12 * 683901; s12 = 0; carry0 = (s0 + (1 << 20)) >> 21; s1 += carry0; s0 -= carry0 << 21; carry2 = (s2 + (1 << 20)) >> 21; s3 += carry2; s2 -= carry2 << 21; carry4 = (s4 + (1 << 20)) >> 21; s5 += carry4; s4 -= carry4 << 21; carry6 = (s6 + (1 << 20)) >> 21; s7 += carry6; s6 -= carry6 << 21; carry8 = (s8 + (1 << 20)) >> 21; s9 += carry8; s8 -= carry8 << 21; carry10 = (s10 + (1 << 20)) >> 21; s11 += carry10; s10 -= carry10 << 21; carry1 = (s1 + (1 << 20)) >> 21; s2 += carry1; s1 -= carry1 << 21; carry3 = (s3 + (1 << 20)) >> 21; s4 += carry3; s3 -= carry3 << 21; carry5 = (s5 + (1 << 20)) >> 21; s6 += carry5; s5 -= carry5 << 21; carry7 = (s7 + (1 << 20)) >> 21; s8 += carry7; s7 -= carry7 << 21; carry9 = (s9 + (1 << 20)) >> 21; s10 += carry9; s9 -= carry9 << 21; carry11 = (s11 + (1 << 20)) >> 21; s12 += carry11; s11 -= carry11 << 21; s0 += s12 * 666643; s1 += s12 * 470296; s2 += s12 * 654183; s3 -= s12 * 997805; s4 += s12 * 136657; s5 -= s12 * 683901; s12 = 0; carry0 = s0 >> 21; s1 += carry0; s0 -= carry0 << 21; carry1 = s1 >> 21; s2 += carry1; s1 -= carry1 << 21; carry2 = s2 >> 21; s3 += carry2; s2 -= carry2 << 21; carry3 = s3 >> 21; s4 += carry3; s3 -= carry3 << 21; carry4 = s4 >> 21; s5 += carry4; s4 -= carry4 << 21; carry5 = s5 >> 21; s6 += carry5; s5 -= carry5 << 21; carry6 = s6 >> 21; s7 += carry6; s6 -= carry6 << 21; carry7 = s7 >> 21; s8 += carry7; s7 -= carry7 << 21; carry8 = s8 >> 21; s9 += carry8; s8 -= carry8 << 21; carry9 = s9 >> 21; s10 += carry9; s9 -= carry9 << 21; carry10 = s10 >> 21; s11 += carry10; s10 -= carry10 << 21; carry11 = s11 >> 21; s12 += carry11; s11 -= carry11 << 21; s0 += s12 * 666643; s1 += s12 * 470296; s2 += s12 * 654183; s3 -= s12 * 997805; s4 += s12 * 136657; s5 -= s12 * 683901; s12 = 0; carry0 = s0 >> 21; s1 += carry0; s0 -= carry0 << 21; carry1 = s1 >> 21; s2 += carry1; s1 -= carry1 << 21; carry2 = s2 >> 21; s3 += carry2; s2 -= carry2 << 21; carry3 = s3 >> 21; s4 += carry3; s3 -= carry3 << 21; carry4 = s4 >> 21; s5 += carry4; s4 -= carry4 << 21; carry5 = s5 >> 21; s6 += carry5; s5 -= carry5 << 21; carry6 = s6 >> 21; s7 += carry6; s6 -= carry6 << 21; carry7 = s7 >> 21; s8 += carry7; s7 -= carry7 << 21; carry8 = s8 >> 21; s9 += carry8; s8 -= carry8 << 21; carry9 = s9 >> 21; s10 += carry9; s9 -= carry9 << 21; carry10 = s10 >> 21; s11 += carry10; s10 -= carry10 << 21; s[0] = (unsigned char) (s0 >> 0); s[1] = (unsigned char) (s0 >> 8); s[2] = (unsigned char) ((s0 >> 16) | (s1 << 5)); s[3] = (unsigned char) (s1 >> 3); s[4] = (unsigned char) (s1 >> 11); s[5] = (unsigned char) ((s1 >> 19) | (s2 << 2)); s[6] = (unsigned char) (s2 >> 6); s[7] = (unsigned char) ((s2 >> 14) | (s3 << 7)); s[8] = (unsigned char) (s3 >> 1); s[9] = (unsigned char) (s3 >> 9); s[10] = (unsigned char) ((s3 >> 17) | (s4 << 4)); s[11] = (unsigned char) (s4 >> 4); s[12] = (unsigned char) (s4 >> 12); s[13] = (unsigned char) ((s4 >> 20) | (s5 << 1)); s[14] = (unsigned char) (s5 >> 7); s[15] = (unsigned char) ((s5 >> 15) | (s6 << 6)); s[16] = (unsigned char) (s6 >> 2); s[17] = (unsigned char) (s6 >> 10); s[18] = (unsigned char) ((s6 >> 18) | (s7 << 3)); s[19] = (unsigned char) (s7 >> 5); s[20] = (unsigned char) (s7 >> 13); s[21] = (unsigned char) (s8 >> 0); s[22] = (unsigned char) (s8 >> 8); s[23] = (unsigned char) ((s8 >> 16) | (s9 << 5)); s[24] = (unsigned char) (s9 >> 3); s[25] = (unsigned char) (s9 >> 11); s[26] = (unsigned char) ((s9 >> 19) | (s10 << 2)); s[27] = (unsigned char) (s10 >> 6); s[28] = (unsigned char) ((s10 >> 14) | (s11 << 7)); s[29] = (unsigned char) (s11 >> 1); s[30] = (unsigned char) (s11 >> 9); s[31] = (unsigned char) (s11 >> 17); } /* Input: a[0]+256*a[1]+...+256^31*a[31] = a b[0]+256*b[1]+...+256^31*b[31] = b c[0]+256*c[1]+...+256^31*c[31] = c Output: s[0]+256*s[1]+...+256^31*s[31] = (ab+c) mod l where l = 2^252 + 27742317777372353535851937790883648493. */ void sc_muladd(unsigned char *s, const unsigned char *a, const unsigned char *b, const unsigned char *c) { int64_t a0 = 2097151 & load_3(a); int64_t a1 = 2097151 & (load_4(a + 2) >> 5); int64_t a2 = 2097151 & (load_3(a + 5) >> 2); int64_t a3 = 2097151 & (load_4(a + 7) >> 7); int64_t a4 = 2097151 & (load_4(a + 10) >> 4); int64_t a5 = 2097151 & (load_3(a + 13) >> 1); int64_t a6 = 2097151 & (load_4(a + 15) >> 6); int64_t a7 = 2097151 & (load_3(a + 18) >> 3); int64_t a8 = 2097151 & load_3(a + 21); int64_t a9 = 2097151 & (load_4(a + 23) >> 5); int64_t a10 = 2097151 & (load_3(a + 26) >> 2); int64_t a11 = (load_4(a + 28) >> 7); int64_t b0 = 2097151 & load_3(b); int64_t b1 = 2097151 & (load_4(b + 2) >> 5); int64_t b2 = 2097151 & (load_3(b + 5) >> 2); int64_t b3 = 2097151 & (load_4(b + 7) >> 7); int64_t b4 = 2097151 & (load_4(b + 10) >> 4); int64_t b5 = 2097151 & (load_3(b + 13) >> 1); int64_t b6 = 2097151 & (load_4(b + 15) >> 6); int64_t b7 = 2097151 & (load_3(b + 18) >> 3); int64_t b8 = 2097151 & load_3(b + 21); int64_t b9 = 2097151 & (load_4(b + 23) >> 5); int64_t b10 = 2097151 & (load_3(b + 26) >> 2); int64_t b11 = (load_4(b + 28) >> 7); int64_t c0 = 2097151 & load_3(c); int64_t c1 = 2097151 & (load_4(c + 2) >> 5); int64_t c2 = 2097151 & (load_3(c + 5) >> 2); int64_t c3 = 2097151 & (load_4(c + 7) >> 7); int64_t c4 = 2097151 & (load_4(c + 10) >> 4); int64_t c5 = 2097151 & (load_3(c + 13) >> 1); int64_t c6 = 2097151 & (load_4(c + 15) >> 6); int64_t c7 = 2097151 & (load_3(c + 18) >> 3); int64_t c8 = 2097151 & load_3(c + 21); int64_t c9 = 2097151 & (load_4(c + 23) >> 5); int64_t c10 = 2097151 & (load_3(c + 26) >> 2); int64_t c11 = (load_4(c + 28) >> 7); int64_t s0; int64_t s1; int64_t s2; int64_t s3; int64_t s4; int64_t s5; int64_t s6; int64_t s7; int64_t s8; int64_t s9; int64_t s10; int64_t s11; int64_t s12; int64_t s13; int64_t s14; int64_t s15; int64_t s16; int64_t s17; int64_t s18; int64_t s19; int64_t s20; int64_t s21; int64_t s22; int64_t s23; int64_t carry0; int64_t carry1; int64_t carry2; int64_t carry3; int64_t carry4; int64_t carry5; int64_t carry6; int64_t carry7; int64_t carry8; int64_t carry9; int64_t carry10; int64_t carry11; int64_t carry12; int64_t carry13; int64_t carry14; int64_t carry15; int64_t carry16; int64_t carry17; int64_t carry18; int64_t carry19; int64_t carry20; int64_t carry21; int64_t carry22; s0 = c0 + a0 * b0; s1 = c1 + a0 * b1 + a1 * b0; s2 = c2 + a0 * b2 + a1 * b1 + a2 * b0; s3 = c3 + a0 * b3 + a1 * b2 + a2 * b1 + a3 * b0; s4 = c4 + a0 * b4 + a1 * b3 + a2 * b2 + a3 * b1 + a4 * b0; s5 = c5 + a0 * b5 + a1 * b4 + a2 * b3 + a3 * b2 + a4 * b1 + a5 * b0; s6 = c6 + a0 * b6 + a1 * b5 + a2 * b4 + a3 * b3 + a4 * b2 + a5 * b1 + a6 * b0; s7 = c7 + a0 * b7 + a1 * b6 + a2 * b5 + a3 * b4 + a4 * b3 + a5 * b2 + a6 * b1 + a7 * b0; s8 = c8 + a0 * b8 + a1 * b7 + a2 * b6 + a3 * b5 + a4 * b4 + a5 * b3 + a6 * b2 + a7 * b1 + a8 * b0; s9 = c9 + a0 * b9 + a1 * b8 + a2 * b7 + a3 * b6 + a4 * b5 + a5 * b4 + a6 * b3 + a7 * b2 + a8 * b1 + a9 * b0; s10 = c10 + a0 * b10 + a1 * b9 + a2 * b8 + a3 * b7 + a4 * b6 + a5 * b5 + a6 * b4 + a7 * b3 + a8 * b2 + a9 * b1 + a10 * b0; s11 = c11 + a0 * b11 + a1 * b10 + a2 * b9 + a3 * b8 + a4 * b7 + a5 * b6 + a6 * b5 + a7 * b4 + a8 * b3 + a9 * b2 + a10 * b1 + a11 * b0; s12 = a1 * b11 + a2 * b10 + a3 * b9 + a4 * b8 + a5 * b7 + a6 * b6 + a7 * b5 + a8 * b4 + a9 * b3 + a10 * b2 + a11 * b1; s13 = a2 * b11 + a3 * b10 + a4 * b9 + a5 * b8 + a6 * b7 + a7 * b6 + a8 * b5 + a9 * b4 + a10 * b3 + a11 * b2; s14 = a3 * b11 + a4 * b10 + a5 * b9 + a6 * b8 + a7 * b7 + a8 * b6 + a9 * b5 + a10 * b4 + a11 * b3; s15 = a4 * b11 + a5 * b10 + a6 * b9 + a7 * b8 + a8 * b7 + a9 * b6 + a10 * b5 + a11 * b4; s16 = a5 * b11 + a6 * b10 + a7 * b9 + a8 * b8 + a9 * b7 + a10 * b6 + a11 * b5; s17 = a6 * b11 + a7 * b10 + a8 * b9 + a9 * b8 + a10 * b7 + a11 * b6; s18 = a7 * b11 + a8 * b10 + a9 * b9 + a10 * b8 + a11 * b7; s19 = a8 * b11 + a9 * b10 + a10 * b9 + a11 * b8; s20 = a9 * b11 + a10 * b10 + a11 * b9; s21 = a10 * b11 + a11 * b10; s22 = a11 * b11; s23 = 0; carry0 = (s0 + (1 << 20)) >> 21; s1 += carry0; s0 -= carry0 << 21; carry2 = (s2 + (1 << 20)) >> 21; s3 += carry2; s2 -= carry2 << 21; carry4 = (s4 + (1 << 20)) >> 21; s5 += carry4; s4 -= carry4 << 21; carry6 = (s6 + (1 << 20)) >> 21; s7 += carry6; s6 -= carry6 << 21; carry8 = (s8 + (1 << 20)) >> 21; s9 += carry8; s8 -= carry8 << 21; carry10 = (s10 + (1 << 20)) >> 21; s11 += carry10; s10 -= carry10 << 21; carry12 = (s12 + (1 << 20)) >> 21; s13 += carry12; s12 -= carry12 << 21; carry14 = (s14 + (1 << 20)) >> 21; s15 += carry14; s14 -= carry14 << 21; carry16 = (s16 + (1 << 20)) >> 21; s17 += carry16; s16 -= carry16 << 21; carry18 = (s18 + (1 << 20)) >> 21; s19 += carry18; s18 -= carry18 << 21; carry20 = (s20 + (1 << 20)) >> 21; s21 += carry20; s20 -= carry20 << 21; carry22 = (s22 + (1 << 20)) >> 21; s23 += carry22; s22 -= carry22 << 21; carry1 = (s1 + (1 << 20)) >> 21; s2 += carry1; s1 -= carry1 << 21; carry3 = (s3 + (1 << 20)) >> 21; s4 += carry3; s3 -= carry3 << 21; carry5 = (s5 + (1 << 20)) >> 21; s6 += carry5; s5 -= carry5 << 21; carry7 = (s7 + (1 << 20)) >> 21; s8 += carry7; s7 -= carry7 << 21; carry9 = (s9 + (1 << 20)) >> 21; s10 += carry9; s9 -= carry9 << 21; carry11 = (s11 + (1 << 20)) >> 21; s12 += carry11; s11 -= carry11 << 21; carry13 = (s13 + (1 << 20)) >> 21; s14 += carry13; s13 -= carry13 << 21; carry15 = (s15 + (1 << 20)) >> 21; s16 += carry15; s15 -= carry15 << 21; carry17 = (s17 + (1 << 20)) >> 21; s18 += carry17; s17 -= carry17 << 21; carry19 = (s19 + (1 << 20)) >> 21; s20 += carry19; s19 -= carry19 << 21; carry21 = (s21 + (1 << 20)) >> 21; s22 += carry21; s21 -= carry21 << 21; s11 += s23 * 666643; s12 += s23 * 470296; s13 += s23 * 654183; s14 -= s23 * 997805; s15 += s23 * 136657; s16 -= s23 * 683901; s23 = 0; s10 += s22 * 666643; s11 += s22 * 470296; s12 += s22 * 654183; s13 -= s22 * 997805; s14 += s22 * 136657; s15 -= s22 * 683901; s22 = 0; s9 += s21 * 666643; s10 += s21 * 470296; s11 += s21 * 654183; s12 -= s21 * 997805; s13 += s21 * 136657; s14 -= s21 * 683901; s21 = 0; s8 += s20 * 666643; s9 += s20 * 470296; s10 += s20 * 654183; s11 -= s20 * 997805; s12 += s20 * 136657; s13 -= s20 * 683901; s20 = 0; s7 += s19 * 666643; s8 += s19 * 470296; s9 += s19 * 654183; s10 -= s19 * 997805; s11 += s19 * 136657; s12 -= s19 * 683901; s19 = 0; s6 += s18 * 666643; s7 += s18 * 470296; s8 += s18 * 654183; s9 -= s18 * 997805; s10 += s18 * 136657; s11 -= s18 * 683901; s18 = 0; carry6 = (s6 + (1 << 20)) >> 21; s7 += carry6; s6 -= carry6 << 21; carry8 = (s8 + (1 << 20)) >> 21; s9 += carry8; s8 -= carry8 << 21; carry10 = (s10 + (1 << 20)) >> 21; s11 += carry10; s10 -= carry10 << 21; carry12 = (s12 + (1 << 20)) >> 21; s13 += carry12; s12 -= carry12 << 21; carry14 = (s14 + (1 << 20)) >> 21; s15 += carry14; s14 -= carry14 << 21; carry16 = (s16 + (1 << 20)) >> 21; s17 += carry16; s16 -= carry16 << 21; carry7 = (s7 + (1 << 20)) >> 21; s8 += carry7; s7 -= carry7 << 21; carry9 = (s9 + (1 << 20)) >> 21; s10 += carry9; s9 -= carry9 << 21; carry11 = (s11 + (1 << 20)) >> 21; s12 += carry11; s11 -= carry11 << 21; carry13 = (s13 + (1 << 20)) >> 21; s14 += carry13; s13 -= carry13 << 21; carry15 = (s15 + (1 << 20)) >> 21; s16 += carry15; s15 -= carry15 << 21; s5 += s17 * 666643; s6 += s17 * 470296; s7 += s17 * 654183; s8 -= s17 * 997805; s9 += s17 * 136657; s10 -= s17 * 683901; s17 = 0; s4 += s16 * 666643; s5 += s16 * 470296; s6 += s16 * 654183; s7 -= s16 * 997805; s8 += s16 * 136657; s9 -= s16 * 683901; s16 = 0; s3 += s15 * 666643; s4 += s15 * 470296; s5 += s15 * 654183; s6 -= s15 * 997805; s7 += s15 * 136657; s8 -= s15 * 683901; s15 = 0; s2 += s14 * 666643; s3 += s14 * 470296; s4 += s14 * 654183; s5 -= s14 * 997805; s6 += s14 * 136657; s7 -= s14 * 683901; s14 = 0; s1 += s13 * 666643; s2 += s13 * 470296; s3 += s13 * 654183; s4 -= s13 * 997805; s5 += s13 * 136657; s6 -= s13 * 683901; s13 = 0; s0 += s12 * 666643; s1 += s12 * 470296; s2 += s12 * 654183; s3 -= s12 * 997805; s4 += s12 * 136657; s5 -= s12 * 683901; s12 = 0; carry0 = (s0 + (1 << 20)) >> 21; s1 += carry0; s0 -= carry0 << 21; carry2 = (s2 + (1 << 20)) >> 21; s3 += carry2; s2 -= carry2 << 21; carry4 = (s4 + (1 << 20)) >> 21; s5 += carry4; s4 -= carry4 << 21; carry6 = (s6 + (1 << 20)) >> 21; s7 += carry6; s6 -= carry6 << 21; carry8 = (s8 + (1 << 20)) >> 21; s9 += carry8; s8 -= carry8 << 21; carry10 = (s10 + (1 << 20)) >> 21; s11 += carry10; s10 -= carry10 << 21; carry1 = (s1 + (1 << 20)) >> 21; s2 += carry1; s1 -= carry1 << 21; carry3 = (s3 + (1 << 20)) >> 21; s4 += carry3; s3 -= carry3 << 21; carry5 = (s5 + (1 << 20)) >> 21; s6 += carry5; s5 -= carry5 << 21; carry7 = (s7 + (1 << 20)) >> 21; s8 += carry7; s7 -= carry7 << 21; carry9 = (s9 + (1 << 20)) >> 21; s10 += carry9; s9 -= carry9 << 21; carry11 = (s11 + (1 << 20)) >> 21; s12 += carry11; s11 -= carry11 << 21; s0 += s12 * 666643; s1 += s12 * 470296; s2 += s12 * 654183; s3 -= s12 * 997805; s4 += s12 * 136657; s5 -= s12 * 683901; s12 = 0; carry0 = s0 >> 21; s1 += carry0; s0 -= carry0 << 21; carry1 = s1 >> 21; s2 += carry1; s1 -= carry1 << 21; carry2 = s2 >> 21; s3 += carry2; s2 -= carry2 << 21; carry3 = s3 >> 21; s4 += carry3; s3 -= carry3 << 21; carry4 = s4 >> 21; s5 += carry4; s4 -= carry4 << 21; carry5 = s5 >> 21; s6 += carry5; s5 -= carry5 << 21; carry6 = s6 >> 21; s7 += carry6; s6 -= carry6 << 21; carry7 = s7 >> 21; s8 += carry7; s7 -= carry7 << 21; carry8 = s8 >> 21; s9 += carry8; s8 -= carry8 << 21; carry9 = s9 >> 21; s10 += carry9; s9 -= carry9 << 21; carry10 = s10 >> 21; s11 += carry10; s10 -= carry10 << 21; carry11 = s11 >> 21; s12 += carry11; s11 -= carry11 << 21; s0 += s12 * 666643; s1 += s12 * 470296; s2 += s12 * 654183; s3 -= s12 * 997805; s4 += s12 * 136657; s5 -= s12 * 683901; s12 = 0; carry0 = s0 >> 21; s1 += carry0; s0 -= carry0 << 21; carry1 = s1 >> 21; s2 += carry1; s1 -= carry1 << 21; carry2 = s2 >> 21; s3 += carry2; s2 -= carry2 << 21; carry3 = s3 >> 21; s4 += carry3; s3 -= carry3 << 21; carry4 = s4 >> 21; s5 += carry4; s4 -= carry4 << 21; carry5 = s5 >> 21; s6 += carry5; s5 -= carry5 << 21; carry6 = s6 >> 21; s7 += carry6; s6 -= carry6 << 21; carry7 = s7 >> 21; s8 += carry7; s7 -= carry7 << 21; carry8 = s8 >> 21; s9 += carry8; s8 -= carry8 << 21; carry9 = s9 >> 21; s10 += carry9; s9 -= carry9 << 21; carry10 = s10 >> 21; s11 += carry10; s10 -= carry10 << 21; s[0] = (unsigned char) (s0 >> 0); s[1] = (unsigned char) (s0 >> 8); s[2] = (unsigned char) ((s0 >> 16) | (s1 << 5)); s[3] = (unsigned char) (s1 >> 3); s[4] = (unsigned char) (s1 >> 11); s[5] = (unsigned char) ((s1 >> 19) | (s2 << 2)); s[6] = (unsigned char) (s2 >> 6); s[7] = (unsigned char) ((s2 >> 14) | (s3 << 7)); s[8] = (unsigned char) (s3 >> 1); s[9] = (unsigned char) (s3 >> 9); s[10] = (unsigned char) ((s3 >> 17) | (s4 << 4)); s[11] = (unsigned char) (s4 >> 4); s[12] = (unsigned char) (s4 >> 12); s[13] = (unsigned char) ((s4 >> 20) | (s5 << 1)); s[14] = (unsigned char) (s5 >> 7); s[15] = (unsigned char) ((s5 >> 15) | (s6 << 6)); s[16] = (unsigned char) (s6 >> 2); s[17] = (unsigned char) (s6 >> 10); s[18] = (unsigned char) ((s6 >> 18) | (s7 << 3)); s[19] = (unsigned char) (s7 >> 5); s[20] = (unsigned char) (s7 >> 13); s[21] = (unsigned char) (s8 >> 0); s[22] = (unsigned char) (s8 >> 8); s[23] = (unsigned char) ((s8 >> 16) | (s9 << 5)); s[24] = (unsigned char) (s9 >> 3); s[25] = (unsigned char) (s9 >> 11); s[26] = (unsigned char) ((s9 >> 19) | (s10 << 2)); s[27] = (unsigned char) (s10 >> 6); s[28] = (unsigned char) ((s10 >> 14) | (s11 << 7)); s[29] = (unsigned char) (s11 >> 1); s[30] = (unsigned char) (s11 >> 9); s[31] = (unsigned char) (s11 >> 17); } opengnb-ver1.6.0.a/libs/ed25519/sc.h000066400000000000000000000004131500454252100166030ustar00rootroot00000000000000#ifndef SC_H #define SC_H /* The set of scalars is \Z/l where l = 2^252 + 27742317777372353535851937790883648493. */ void sc_reduce(unsigned char *s); void sc_muladd(unsigned char *s, const unsigned char *a, const unsigned char *b, const unsigned char *c); #endif opengnb-ver1.6.0.a/libs/ed25519/seed.c000066400000000000000000000012041500454252100171100ustar00rootroot00000000000000#include "ed25519.h" #ifndef ED25519_NO_SEED #ifdef _WIN32 #include #include #else #include #endif int ed25519_create_seed(unsigned char *seed) { #ifdef _WIN32 HCRYPTPROV prov; if (!CryptAcquireContext(&prov, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) { return 1; } if (!CryptGenRandom(prov, 32, seed)) { CryptReleaseContext(prov, 0); return 1; } CryptReleaseContext(prov, 0); #else FILE *f = fopen("/dev/urandom", "rb"); if (f == NULL) { return 1; } fread(seed, 1, 32, f); fclose(f); #endif return 0; } #endif opengnb-ver1.6.0.a/libs/ed25519/sha512.c000066400000000000000000000255201500454252100172020ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis * * LibTomCrypt is a library that provides various cryptographic * algorithms in a highly modular and flexible manner. * * The library is free for all purposes without any express * guarantee it works. * * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ #include "fixedint.h" #include "sha512.h" /* the K array */ static const uint64_t K[80] = { UINT64_C(0x428a2f98d728ae22), UINT64_C(0x7137449123ef65cd), UINT64_C(0xb5c0fbcfec4d3b2f), UINT64_C(0xe9b5dba58189dbbc), UINT64_C(0x3956c25bf348b538), UINT64_C(0x59f111f1b605d019), UINT64_C(0x923f82a4af194f9b), UINT64_C(0xab1c5ed5da6d8118), UINT64_C(0xd807aa98a3030242), UINT64_C(0x12835b0145706fbe), UINT64_C(0x243185be4ee4b28c), UINT64_C(0x550c7dc3d5ffb4e2), UINT64_C(0x72be5d74f27b896f), UINT64_C(0x80deb1fe3b1696b1), UINT64_C(0x9bdc06a725c71235), UINT64_C(0xc19bf174cf692694), UINT64_C(0xe49b69c19ef14ad2), UINT64_C(0xefbe4786384f25e3), UINT64_C(0x0fc19dc68b8cd5b5), UINT64_C(0x240ca1cc77ac9c65), UINT64_C(0x2de92c6f592b0275), UINT64_C(0x4a7484aa6ea6e483), UINT64_C(0x5cb0a9dcbd41fbd4), UINT64_C(0x76f988da831153b5), UINT64_C(0x983e5152ee66dfab), UINT64_C(0xa831c66d2db43210), UINT64_C(0xb00327c898fb213f), UINT64_C(0xbf597fc7beef0ee4), UINT64_C(0xc6e00bf33da88fc2), UINT64_C(0xd5a79147930aa725), UINT64_C(0x06ca6351e003826f), UINT64_C(0x142929670a0e6e70), UINT64_C(0x27b70a8546d22ffc), UINT64_C(0x2e1b21385c26c926), UINT64_C(0x4d2c6dfc5ac42aed), UINT64_C(0x53380d139d95b3df), UINT64_C(0x650a73548baf63de), UINT64_C(0x766a0abb3c77b2a8), UINT64_C(0x81c2c92e47edaee6), UINT64_C(0x92722c851482353b), UINT64_C(0xa2bfe8a14cf10364), UINT64_C(0xa81a664bbc423001), UINT64_C(0xc24b8b70d0f89791), UINT64_C(0xc76c51a30654be30), UINT64_C(0xd192e819d6ef5218), UINT64_C(0xd69906245565a910), UINT64_C(0xf40e35855771202a), UINT64_C(0x106aa07032bbd1b8), UINT64_C(0x19a4c116b8d2d0c8), UINT64_C(0x1e376c085141ab53), UINT64_C(0x2748774cdf8eeb99), UINT64_C(0x34b0bcb5e19b48a8), UINT64_C(0x391c0cb3c5c95a63), UINT64_C(0x4ed8aa4ae3418acb), UINT64_C(0x5b9cca4f7763e373), UINT64_C(0x682e6ff3d6b2b8a3), UINT64_C(0x748f82ee5defb2fc), UINT64_C(0x78a5636f43172f60), UINT64_C(0x84c87814a1f0ab72), UINT64_C(0x8cc702081a6439ec), UINT64_C(0x90befffa23631e28), UINT64_C(0xa4506cebde82bde9), UINT64_C(0xbef9a3f7b2c67915), UINT64_C(0xc67178f2e372532b), UINT64_C(0xca273eceea26619c), UINT64_C(0xd186b8c721c0c207), UINT64_C(0xeada7dd6cde0eb1e), UINT64_C(0xf57d4f7fee6ed178), UINT64_C(0x06f067aa72176fba), UINT64_C(0x0a637dc5a2c898a6), UINT64_C(0x113f9804bef90dae), UINT64_C(0x1b710b35131c471b), UINT64_C(0x28db77f523047d84), UINT64_C(0x32caab7b40c72493), UINT64_C(0x3c9ebe0a15c9bebc), UINT64_C(0x431d67c49c100d4c), UINT64_C(0x4cc5d4becb3e42b6), UINT64_C(0x597f299cfc657e2a), UINT64_C(0x5fcb6fab3ad6faec), UINT64_C(0x6c44198c4a475817) }; /* Various logical functions */ #define ROR64c(x, y) \ ( ((((x)&UINT64_C(0xFFFFFFFFFFFFFFFF))>>((uint64_t)(y)&UINT64_C(63))) | \ ((x)<<((uint64_t)(64-((y)&UINT64_C(63)))))) & UINT64_C(0xFFFFFFFFFFFFFFFF)) #define STORE64H(x, y) \ { (y)[0] = (unsigned char)(((x)>>56)&255); (y)[1] = (unsigned char)(((x)>>48)&255); \ (y)[2] = (unsigned char)(((x)>>40)&255); (y)[3] = (unsigned char)(((x)>>32)&255); \ (y)[4] = (unsigned char)(((x)>>24)&255); (y)[5] = (unsigned char)(((x)>>16)&255); \ (y)[6] = (unsigned char)(((x)>>8)&255); (y)[7] = (unsigned char)((x)&255); } #define LOAD64H(x, y) \ { x = (((uint64_t)((y)[0] & 255))<<56)|(((uint64_t)((y)[1] & 255))<<48) | \ (((uint64_t)((y)[2] & 255))<<40)|(((uint64_t)((y)[3] & 255))<<32) | \ (((uint64_t)((y)[4] & 255))<<24)|(((uint64_t)((y)[5] & 255))<<16) | \ (((uint64_t)((y)[6] & 255))<<8)|(((uint64_t)((y)[7] & 255))); } #define Ch(x,y,z) (z ^ (x & (y ^ z))) #define Maj(x,y,z) (((x | y) & z) | (x & y)) #define S(x, n) ROR64c(x, n) #define R(x, n) (((x) &UINT64_C(0xFFFFFFFFFFFFFFFF))>>((uint64_t)n)) #define Sigma0(x) (S(x, 28) ^ S(x, 34) ^ S(x, 39)) #define Sigma1(x) (S(x, 14) ^ S(x, 18) ^ S(x, 41)) #define Gamma0(x) (S(x, 1) ^ S(x, 8) ^ R(x, 7)) #define Gamma1(x) (S(x, 19) ^ S(x, 61) ^ R(x, 6)) #ifndef MIN #define MIN(x, y) ( ((x)<(y))?(x):(y) ) #endif /* compress 1024-bits */ static int sha512_compress(sha512_context *md, unsigned char *buf) { uint64_t S[8], W[80], t0, t1; int i; /* copy state into S */ for (i = 0; i < 8; i++) { S[i] = md->state[i]; } /* copy the state into 1024-bits into W[0..15] */ for (i = 0; i < 16; i++) { LOAD64H(W[i], buf + (8*i)); } /* fill W[16..79] */ for (i = 16; i < 80; i++) { W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + W[i - 16]; } /* Compress */ #define RND(a,b,c,d,e,f,g,h,i) \ t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i]; \ t1 = Sigma0(a) + Maj(a, b, c);\ d += t0; \ h = t0 + t1; for (i = 0; i < 80; i += 8) { RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],i+0); RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],i+1); RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],i+2); RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],i+3); RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],i+4); RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],i+5); RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],i+6); RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],i+7); } #undef RND /* feedback */ for (i = 0; i < 8; i++) { md->state[i] = md->state[i] + S[i]; } return 0; } /** Initialize the hash state @param md The hash state you wish to initialize @return 0 if successful */ int sha512_init(sha512_context * md) { if (md == NULL) return 1; md->curlen = 0; md->length = 0; md->state[0] = UINT64_C(0x6a09e667f3bcc908); md->state[1] = UINT64_C(0xbb67ae8584caa73b); md->state[2] = UINT64_C(0x3c6ef372fe94f82b); md->state[3] = UINT64_C(0xa54ff53a5f1d36f1); md->state[4] = UINT64_C(0x510e527fade682d1); md->state[5] = UINT64_C(0x9b05688c2b3e6c1f); md->state[6] = UINT64_C(0x1f83d9abfb41bd6b); md->state[7] = UINT64_C(0x5be0cd19137e2179); return 0; } /** Process a block of memory though the hash @param md The hash state @param in The data to hash @param inlen The length of the data (octets) @return 0 if successful */ int sha512_update (sha512_context * md, const unsigned char *in, size_t inlen) { size_t n; size_t i; int err; if (md == NULL) return 1; if (in == NULL) return 1; if (md->curlen > sizeof(md->buf)) { return 1; } while (inlen > 0) { if (md->curlen == 0 && inlen >= 128) { if ((err = sha512_compress (md, (unsigned char *)in)) != 0) { return err; } md->length += 128 * 8; in += 128; inlen -= 128; } else { n = MIN(inlen, (128 - md->curlen)); for (i = 0; i < n; i++) { md->buf[i + md->curlen] = in[i]; } md->curlen += n; in += n; inlen -= n; if (md->curlen == 128) { if ((err = sha512_compress (md, md->buf)) != 0) { return err; } md->length += 8*128; md->curlen = 0; } } } return 0; } /** Terminate the hash to get the digest @param md The hash state @param out [out] The destination of the hash (64 bytes) @return 0 if successful */ int sha512_final(sha512_context * md, unsigned char *out) { int i; if (md == NULL) return 1; if (out == NULL) return 1; if (md->curlen >= sizeof(md->buf)) { return 1; } /* increase the length of the message */ md->length += md->curlen * UINT64_C(8); /* append the '1' bit */ md->buf[md->curlen++] = (unsigned char)0x80; /* if the length is currently above 112 bytes we append zeros * then compress. Then we can fall back to padding zeros and length * encoding like normal. */ if (md->curlen > 112) { while (md->curlen < 128) { md->buf[md->curlen++] = (unsigned char)0; } sha512_compress(md, md->buf); md->curlen = 0; } /* pad upto 120 bytes of zeroes * note: that from 112 to 120 is the 64 MSB of the length. We assume that you won't hash * > 2^64 bits of data... :-) */ while (md->curlen < 120) { md->buf[md->curlen++] = (unsigned char)0; } /* store length */ STORE64H(md->length, md->buf+120); sha512_compress(md, md->buf); /* copy output */ for (i = 0; i < 8; i++) { STORE64H(md->state[i], out+(8*i)); } return 0; } int sha512(const unsigned char *message, size_t message_len, unsigned char *out) { sha512_context ctx; int ret; if ((ret = sha512_init(&ctx))) return ret; if ((ret = sha512_update(&ctx, message, message_len))) return ret; if ((ret = sha512_final(&ctx, out))) return ret; return 0; } opengnb-ver1.6.0.a/libs/ed25519/sha512.h000066400000000000000000000007511500454252100172060ustar00rootroot00000000000000#ifndef SHA512_H #define SHA512_H #include #include "fixedint.h" /* state */ typedef struct sha512_context_ { uint64_t length, state[8]; size_t curlen; unsigned char buf[128]; } sha512_context; int sha512_init(sha512_context * md); int sha512_final(sha512_context * md, unsigned char *out); int sha512_update(sha512_context * md, const unsigned char *in, size_t inlen); int sha512(const unsigned char *message, size_t message_len, unsigned char *out); #endif opengnb-ver1.6.0.a/libs/ed25519/sign.c000066400000000000000000000014731500454252100171400ustar00rootroot00000000000000#include "ed25519.h" #include "sha512.h" #include "ge.h" #include "sc.h" void ed25519_sign(unsigned char *signature, const unsigned char *message, size_t message_len, const unsigned char *public_key, const unsigned char *private_key) { sha512_context hash; unsigned char hram[64]; unsigned char r[64]; ge_p3 R; sha512_init(&hash); sha512_update(&hash, private_key + 32, 32); sha512_update(&hash, message, message_len); sha512_final(&hash, r); sc_reduce(r); ge_scalarmult_base(&R, r); ge_p3_tobytes(signature, &R); sha512_init(&hash); sha512_update(&hash, signature, 32); sha512_update(&hash, public_key, 32); sha512_update(&hash, message, message_len); sha512_final(&hash, hram); sc_reduce(hram); sc_muladd(signature + 32, hram, private_key, r); } opengnb-ver1.6.0.a/libs/ed25519/verify.c000066400000000000000000000025271500454252100175050ustar00rootroot00000000000000#include "ed25519.h" #include "sha512.h" #include "ge.h" #include "sc.h" static int consttime_equal(const unsigned char *x, const unsigned char *y) { unsigned char r = 0; r = x[0] ^ y[0]; #define F(i) r |= x[i] ^ y[i] F(1); F(2); F(3); F(4); F(5); F(6); F(7); F(8); F(9); F(10); F(11); F(12); F(13); F(14); F(15); F(16); F(17); F(18); F(19); F(20); F(21); F(22); F(23); F(24); F(25); F(26); F(27); F(28); F(29); F(30); F(31); #undef F return !r; } int ed25519_verify(const unsigned char *signature, const unsigned char *message, size_t message_len, const unsigned char *public_key) { unsigned char h[64]; unsigned char checker[32]; sha512_context hash; ge_p3 A; ge_p2 R; if (signature[63] & 224) { return 0; } if (ge_frombytes_negate_vartime(&A, public_key) != 0) { return 0; } sha512_init(&hash); sha512_update(&hash, signature, 32); sha512_update(&hash, public_key, 32); sha512_update(&hash, message, message_len); sha512_final(&hash, h); sc_reduce(h); ge_double_scalarmult_vartime(&R, h, &A, signature + 32); ge_tobytes(checker, &R); if (!consttime_equal(checker, signature)) { return 0; } return 1; } opengnb-ver1.6.0.a/libs/hash/000077500000000000000000000000001500454252100157545ustar00rootroot00000000000000opengnb-ver1.6.0.a/libs/hash/murmurhash.c000066400000000000000000000013631500454252100203160ustar00rootroot00000000000000#include #include //from nginx source code uint32_t murmurhash_hash(unsigned char *data, size_t len){ uint32_t h, k; h = 0 ^ (uint32_t)len; while (len >= 4) { k = data[0]; k |= data[1] << 8; k |= data[2] << 16; k |= data[3] << 24; k *= 0x5bd1e995; k ^= k >> 24; k *= 0x5bd1e995; h *= 0x5bd1e995; h ^= k; data += 4; len -= 4; } switch (len) { case 3: h ^= data[2] << 16; /* fall through */ case 2: h ^= data[1] << 8; /* fall through */ case 1: h ^= data[0]; h *= 0x5bd1e995; } h ^= h >> 13; h *= 0x5bd1e995; h ^= h >> 15; return h; } opengnb-ver1.6.0.a/libs/libnatpmp/000077500000000000000000000000001500454252100170175ustar00rootroot00000000000000opengnb-ver1.6.0.a/libs/libnatpmp/LICENSE000066400000000000000000000026761500454252100200370ustar00rootroot00000000000000Copyright (c) 2007-2011, Thomas BERNARD All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * 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. * The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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. opengnb-ver1.6.0.a/libs/libnatpmp/declspec.h000066400000000000000000000007171500454252100207570ustar00rootroot00000000000000#ifndef DECLSPEC_H_INCLUDED #define DECLSPEC_H_INCLUDED #if defined(WIN32) && !defined(NATPMP_STATICLIB) /* for windows dll */ #ifdef NATPMP_EXPORTS #define LIBSPEC __declspec(dllexport) #else #define LIBSPEC __declspec(dllimport) #endif #else #if defined(__GNUC__) && __GNUC__ >= 4 /* fix dynlib for OS X 10.9.2 and Apple LLVM version 5.0 */ #define LIBSPEC __attribute__ ((visibility ("default"))) #else #define LIBSPEC #endif #endif #endif opengnb-ver1.6.0.a/libs/libnatpmp/getgateway.c000066400000000000000000000440151500454252100213300ustar00rootroot00000000000000/* $Id: getgateway.c,v 1.25 2014/04/22 10:28:57 nanard Exp $ */ /* libnatpmp Copyright (c) 2007-2014, Thomas BERNARD All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * 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. * The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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. */ #include #include #ifndef WIN32 #include #endif #if !defined(_MSC_VER) #include #endif /* There is no portable method to get the default route gateway. * So below are four (or five ?) differents functions implementing this. * Parsing /proc/net/route is for linux. * sysctl is the way to access such informations on BSD systems. * Many systems should provide route information through raw PF_ROUTE * sockets. * In MS Windows, default gateway is found by looking into the registry * or by using GetBestRoute(). */ #ifdef __linux__ #define USE_PROC_NET_ROUTE #undef USE_SOCKET_ROUTE #undef USE_SYSCTL_NET_ROUTE #endif #if defined(BSD) || defined(__FreeBSD_kernel__) #undef USE_PROC_NET_ROUTE #define USE_SOCKET_ROUTE #undef USE_SYSCTL_NET_ROUTE #endif #ifdef __APPLE__ #undef USE_PROC_NET_ROUTE #undef USE_SOCKET_ROUTE #define USE_SYSCTL_NET_ROUTE #endif #if (defined(sun) && defined(__SVR4)) #undef USE_PROC_NET_ROUTE #define USE_SOCKET_ROUTE #undef USE_SYSCTL_NET_ROUTE #endif #ifdef WIN32 #undef USE_PROC_NET_ROUTE #undef USE_SOCKET_ROUTE #undef USE_SYSCTL_NET_ROUTE //#define USE_WIN32_CODE #define USE_WIN32_CODE_2 #endif #ifdef __CYGWIN__ #undef USE_PROC_NET_ROUTE #undef USE_SOCKET_ROUTE #undef USE_SYSCTL_NET_ROUTE #define USE_WIN32_CODE #include #include #include #include #endif #ifdef __HAIKU__ #include #include #include #include #define USE_HAIKU_CODE #endif #ifdef USE_SYSCTL_NET_ROUTE #include #include #include #include #endif #ifdef USE_SOCKET_ROUTE #include #include #include #include #include #endif #ifdef USE_WIN32_CODE #include #include #define MAX_KEY_LENGTH 255 #define MAX_VALUE_LENGTH 16383 #endif #ifdef USE_WIN32_CODE_2 #include #include #endif #include "getgateway.h" #ifndef WIN32 #define SUCCESS (0) #define FAILED (-1) #endif #ifdef USE_PROC_NET_ROUTE /* parse /proc/net/route which is as follow : Iface Destination Gateway Flags RefCnt Use Metric Mask MTU Window IRTT wlan0 0001A8C0 00000000 0001 0 0 0 00FFFFFF 0 0 0 eth0 0000FEA9 00000000 0001 0 0 0 0000FFFF 0 0 0 wlan0 00000000 0101A8C0 0003 0 0 0 00000000 0 0 0 eth0 00000000 00000000 0001 0 0 1000 00000000 0 0 0 One header line, and then one line by route by route table entry. */ int getdefaultgateway(in_addr_t * addr) { unsigned long d, g; char buf[256]; int line = 0; FILE * f; char * p; f = fopen("/proc/net/route", "r"); if(!f) return FAILED; while(fgets(buf, sizeof(buf), f)) { if(line > 0) { /* skip the first line */ p = buf; /* skip the interface name */ while(*p && !isspace(*p)) p++; while(*p && isspace(*p)) p++; if(sscanf(p, "%lx%lx", &d, &g)==2) { if(d == 0 && g != 0) { /* default */ *addr = g; fclose(f); return SUCCESS; } } } line++; } /* default route not found ! */ if(f) fclose(f); return FAILED; } #endif /* #ifdef USE_PROC_NET_ROUTE */ #ifdef USE_SYSCTL_NET_ROUTE #define ROUNDUP(a) \ ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) int getdefaultgateway(in_addr_t * addr) { #if 0 /* net.route.0.inet.dump.0.0 ? */ int mib[] = {CTL_NET, PF_ROUTE, 0, AF_INET, NET_RT_DUMP, 0, 0/*tableid*/}; #endif /* net.route.0.inet.flags.gateway */ int mib[] = {CTL_NET, PF_ROUTE, 0, AF_INET, NET_RT_FLAGS, RTF_GATEWAY}; size_t l; char * buf, * p; struct rt_msghdr * rt; struct sockaddr * sa; struct sockaddr * sa_tab[RTAX_MAX]; int i; int r = FAILED; if(sysctl(mib, sizeof(mib)/sizeof(int), 0, &l, 0, 0) < 0) { return FAILED; } if(l>0) { buf = malloc(l); if(sysctl(mib, sizeof(mib)/sizeof(int), buf, &l, 0, 0) < 0) { free(buf); return FAILED; } for(p=buf; prtm_msglen) { rt = (struct rt_msghdr *)p; sa = (struct sockaddr *)(rt + 1); for(i=0; irtm_addrs & (1 << i)) { sa_tab[i] = sa; sa = (struct sockaddr *)((char *)sa + ROUNDUP(sa->sa_len)); } else { sa_tab[i] = NULL; } } if( ((rt->rtm_addrs & (RTA_DST|RTA_GATEWAY)) == (RTA_DST|RTA_GATEWAY)) && sa_tab[RTAX_DST]->sa_family == AF_INET && sa_tab[RTAX_GATEWAY]->sa_family == AF_INET) { if(((struct sockaddr_in *)sa_tab[RTAX_DST])->sin_addr.s_addr == 0) { *addr = ((struct sockaddr_in *)(sa_tab[RTAX_GATEWAY]))->sin_addr.s_addr; r = SUCCESS; } } } free(buf); } return r; } #endif /* #ifdef USE_SYSCTL_NET_ROUTE */ #ifdef USE_SOCKET_ROUTE /* Thanks to Darren Kenny for this code */ #define NEXTADDR(w, u) \ if (rtm_addrs & (w)) {\ l = sizeof(struct sockaddr); memmove(cp, &(u), l); cp += l;\ } #define rtm m_rtmsg.m_rtm struct { struct rt_msghdr m_rtm; char m_space[512]; } m_rtmsg; int getdefaultgateway(in_addr_t *addr) { int s, seq, l, rtm_addrs, i; pid_t pid; struct sockaddr so_dst, so_mask; char *cp = m_rtmsg.m_space; struct sockaddr *gate = NULL, *sa; struct rt_msghdr *msg_hdr; pid = getpid(); seq = 0; rtm_addrs = RTA_DST | RTA_NETMASK; memset(&so_dst, 0, sizeof(so_dst)); memset(&so_mask, 0, sizeof(so_mask)); memset(&rtm, 0, sizeof(struct rt_msghdr)); rtm.rtm_type = RTM_GET; rtm.rtm_flags = RTF_UP | RTF_GATEWAY; rtm.rtm_version = RTM_VERSION; rtm.rtm_seq = ++seq; rtm.rtm_addrs = rtm_addrs; so_dst.sa_family = AF_INET; so_mask.sa_family = AF_INET; NEXTADDR(RTA_DST, so_dst); NEXTADDR(RTA_NETMASK, so_mask); rtm.rtm_msglen = l = cp - (char *)&m_rtmsg; s = socket(PF_ROUTE, SOCK_RAW, 0); if (write(s, (char *)&m_rtmsg, l) < 0) { close(s); return FAILED; } do { l = read(s, (char *)&m_rtmsg, sizeof(m_rtmsg)); } while (l > 0 && (rtm.rtm_seq != seq || rtm.rtm_pid != pid)); close(s); msg_hdr = &rtm; cp = ((char *)(msg_hdr + 1)); if (msg_hdr->rtm_addrs) { for (i = 1; i; i <<= 1) if (i & msg_hdr->rtm_addrs) { sa = (struct sockaddr *)cp; if (i == RTA_GATEWAY ) gate = sa; cp += sizeof(struct sockaddr); } } else { return FAILED; } if (gate != NULL ) { *addr = ((struct sockaddr_in *)gate)->sin_addr.s_addr; return SUCCESS; } else { return FAILED; } } #endif /* #ifdef USE_SOCKET_ROUTE */ #ifdef USE_WIN32_CODE LIBSPEC int getdefaultgateway(in_addr_t * addr) { HKEY networkCardsKey; HKEY networkCardKey; HKEY interfacesKey; HKEY interfaceKey; DWORD i = 0; DWORD numSubKeys = 0; TCHAR keyName[MAX_KEY_LENGTH]; DWORD keyNameLength = MAX_KEY_LENGTH; TCHAR keyValue[MAX_VALUE_LENGTH]; DWORD keyValueLength = MAX_VALUE_LENGTH; DWORD keyValueType = REG_SZ; TCHAR gatewayValue[MAX_VALUE_LENGTH]; DWORD gatewayValueLength = MAX_VALUE_LENGTH; DWORD gatewayValueType = REG_MULTI_SZ; int done = 0; //const char * networkCardsPath = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\NetworkCards"; //const char * interfacesPath = "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces"; #ifdef UNICODE LPCTSTR networkCardsPath = L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\NetworkCards"; LPCTSTR interfacesPath = L"SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces"; #define STR_SERVICENAME L"ServiceName" #define STR_DHCPDEFAULTGATEWAY L"DhcpDefaultGateway" #define STR_DEFAULTGATEWAY L"DefaultGateway" #else LPCTSTR networkCardsPath = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\NetworkCards"; LPCTSTR interfacesPath = "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces"; #define STR_SERVICENAME "ServiceName" #define STR_DHCPDEFAULTGATEWAY "DhcpDefaultGateway" #define STR_DEFAULTGATEWAY "DefaultGateway" #endif // The windows registry lists its primary network devices in the following location: // HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\NetworkCards // // Each network device has its own subfolder, named with an index, with various properties: // -NetworkCards // -5 // -Description = Broadcom 802.11n Network Adapter // -ServiceName = {E35A72F8-5065-4097-8DFE-C7790774EE4D} // -8 // -Description = Marvell Yukon 88E8058 PCI-E Gigabit Ethernet Controller // -ServiceName = {86226414-5545-4335-A9D1-5BD7120119AD} // // The above service name is the name of a subfolder within: // HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces // // There may be more subfolders in this interfaces path than listed in the network cards path above: // -Interfaces // -{3a539854-6a70-11db-887c-806e6f6e6963} // -DhcpIPAddress = 0.0.0.0 // -[more] // -{E35A72F8-5065-4097-8DFE-C7790774EE4D} // -DhcpIPAddress = 10.0.1.4 // -DhcpDefaultGateway = 10.0.1.1 // -[more] // -{86226414-5545-4335-A9D1-5BD7120119AD} // -DhcpIpAddress = 10.0.1.5 // -DhcpDefaultGateay = 10.0.1.1 // -[more] // // In order to extract this information, we enumerate each network card, and extract the ServiceName value. // This is then used to open the interface subfolder, and attempt to extract a DhcpDefaultGateway value. // Once one is found, we're done. // // It may be possible to simply enumerate the interface folders until we find one with a DhcpDefaultGateway value. // However, the technique used is the technique most cited on the web, and we assume it to be more correct. if(ERROR_SUCCESS != RegOpenKeyEx(HKEY_LOCAL_MACHINE, // Open registry key or predifined key networkCardsPath, // Name of registry subkey to open 0, // Reserved - must be zero KEY_READ, // Mask - desired access rights &networkCardsKey)) // Pointer to output key { // Unable to open network cards keys return -1; } if(ERROR_SUCCESS != RegOpenKeyEx(HKEY_LOCAL_MACHINE, // Open registry key or predefined key interfacesPath, // Name of registry subkey to open 0, // Reserved - must be zero KEY_READ, // Mask - desired access rights &interfacesKey)) // Pointer to output key { // Unable to open interfaces key RegCloseKey(networkCardsKey); return -1; } // Figure out how many subfolders are within the NetworkCards folder RegQueryInfoKey(networkCardsKey, NULL, NULL, NULL, &numSubKeys, NULL, NULL, NULL, NULL, NULL, NULL, NULL); //printf( "Number of subkeys: %u\n", (unsigned int)numSubKeys); // Enumrate through each subfolder within the NetworkCards folder for(i = 0; i < numSubKeys && !done; i++) { keyNameLength = MAX_KEY_LENGTH; if(ERROR_SUCCESS == RegEnumKeyEx(networkCardsKey, // Open registry key i, // Index of subkey to retrieve keyName, // Buffer that receives the name of the subkey &keyNameLength, // Variable that receives the size of the above buffer NULL, // Reserved - must be NULL NULL, // Buffer that receives the class string NULL, // Variable that receives the size of the above buffer NULL)) // Variable that receives the last write time of subkey { if(RegOpenKeyEx(networkCardsKey, keyName, 0, KEY_READ, &networkCardKey) == ERROR_SUCCESS) { keyValueLength = MAX_VALUE_LENGTH; if(ERROR_SUCCESS == RegQueryValueEx(networkCardKey, // Open registry key STR_SERVICENAME, // Name of key to query NULL, // Reserved - must be NULL &keyValueType, // Receives value type (LPBYTE)keyValue, // Receives value &keyValueLength)) // Receives value length in bytes { // printf("keyValue: %s\n", keyValue); if(RegOpenKeyEx(interfacesKey, keyValue, 0, KEY_READ, &interfaceKey) == ERROR_SUCCESS) { gatewayValueLength = MAX_VALUE_LENGTH; if(ERROR_SUCCESS == RegQueryValueEx(interfaceKey, // Open registry key STR_DHCPDEFAULTGATEWAY, // Name of key to query NULL, // Reserved - must be NULL &gatewayValueType, // Receives value type (LPBYTE)gatewayValue, // Receives value &gatewayValueLength)) // Receives value length in bytes { // Check to make sure it's a string if((gatewayValueType == REG_MULTI_SZ || gatewayValueType == REG_SZ) && (gatewayValueLength > 1)) { //printf("gatewayValue: %s\n", gatewayValue); done = 1; } } else if(ERROR_SUCCESS == RegQueryValueEx(interfaceKey, // Open registry key STR_DEFAULTGATEWAY, // Name of key to query NULL, // Reserved - must be NULL &gatewayValueType, // Receives value type (LPBYTE)gatewayValue,// Receives value &gatewayValueLength)) // Receives value length in bytes { // Check to make sure it's a string if((gatewayValueType == REG_MULTI_SZ || gatewayValueType == REG_SZ) && (gatewayValueLength > 1)) { //printf("gatewayValue: %s\n", gatewayValue); done = 1; } } RegCloseKey(interfaceKey); } } RegCloseKey(networkCardKey); } } } RegCloseKey(interfacesKey); RegCloseKey(networkCardsKey); if(done) { #if UNICODE char tmp[32]; for(i = 0; i < 32; i++) { tmp[i] = (char)gatewayValue[i]; if(!tmp[i]) break; } tmp[31] = '\0'; *addr = inet_addr(tmp); #else *addr = inet_addr(gatewayValue); #endif return 0; } return -1; } #endif /* #ifdef USE_WIN32_CODE */ #ifdef USE_WIN32_CODE_2 int getdefaultgateway(in_addr_t *addr) { MIB_IPFORWARDROW ip_forward; memset(&ip_forward, 0, sizeof(ip_forward)); if(GetBestRoute(inet_addr("0.0.0.0"), 0, &ip_forward) != NO_ERROR) return -1; *addr = ip_forward.dwForwardNextHop; return 0; } #endif /* #ifdef USE_WIN32_CODE_2 */ #ifdef USE_HAIKU_CODE int getdefaultgateway(in_addr_t *addr) { int fd, ret = -1; struct ifconf config; void *buffer = NULL; struct ifreq *interface; if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { return -1; } if (ioctl(fd, SIOCGRTSIZE, &config, sizeof(config)) != 0) { goto fail; } if (config.ifc_value < 1) { goto fail; /* No routes */ } if ((buffer = malloc(config.ifc_value)) == NULL) { goto fail; } config.ifc_len = config.ifc_value; config.ifc_buf = buffer; if (ioctl(fd, SIOCGRTTABLE, &config, sizeof(config)) != 0) { goto fail; } for (interface = buffer; (uint8_t *)interface < (uint8_t *)buffer + config.ifc_len; ) { struct route_entry route = interface->ifr_route; int intfSize; if (route.flags & (RTF_GATEWAY | RTF_DEFAULT)) { *addr = ((struct sockaddr_in *)route.gateway)->sin_addr.s_addr; ret = 0; break; } intfSize = sizeof(route) + IF_NAMESIZE; if (route.destination != NULL) { intfSize += route.destination->sa_len; } if (route.mask != NULL) { intfSize += route.mask->sa_len; } if (route.gateway != NULL) { intfSize += route.gateway->sa_len; } interface = (struct ifreq *)((uint8_t *)interface + intfSize); } fail: free(buffer); close(fd); return ret; } #endif /* #ifdef USE_HAIKU_CODE */ #if !defined(USE_PROC_NET_ROUTE) && !defined(USE_SOCKET_ROUTE) && !defined(USE_SYSCTL_NET_ROUTE) && !defined(USE_WIN32_CODE) && !defined(USE_WIN32_CODE_2) && !defined(USE_HAIKU_CODE) int getdefaultgateway(in_addr_t * addr) { return -1; } #endif opengnb-ver1.6.0.a/libs/libnatpmp/getgateway.h000066400000000000000000000036531500454252100213400ustar00rootroot00000000000000/* $Id: getgateway.h,v 1.8 2014/04/22 09:15:40 nanard Exp $ */ /* libnatpmp Copyright (c) 2007-2014, Thomas BERNARD All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * 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. * The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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. */ #ifndef __GETGATEWAY_H__ #define __GETGATEWAY_H__ #ifdef WIN32 #if !defined(_MSC_VER) || _MSC_VER >= 1600 #include #else typedef unsigned long uint32_t; typedef unsigned short uint16_t; #endif #define in_addr_t uint32_t #endif /* #include "declspec.h" */ /* getdefaultgateway() : * return value : * 0 : success * -1 : failure */ /* LIBSPEC */int getdefaultgateway(in_addr_t * addr); #endif opengnb-ver1.6.0.a/libs/libnatpmp/natpmp.c000066400000000000000000000245311500454252100204670ustar00rootroot00000000000000/* $Id: natpmp.c,v 1.20 2015/05/27 12:43:15 nanard Exp $ */ /* libnatpmp Copyright (c) 2007-2015, Thomas BERNARD All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * 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. * The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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. */ #ifdef __linux__ #define _DEFAULT_SOURCE 1 #endif #include #include #if !defined(_MSC_VER) #include #endif #ifdef WIN32 #include #include #include #include //#define EWOULDBLOCK WSAEWOULDBLOCK //#define ECONNREFUSED WSAECONNREFUSED #include "wingettimeofday.h" #define gettimeofday natpmp_gettimeofday #else #include #include #include #include #include #define closesocket close #endif #include "natpmp.h" #include "getgateway.h" #include LIBSPEC int initnatpmp(natpmp_t * p, int forcegw, in_addr_t forcedgw) { #ifdef WIN32 u_long ioctlArg = 1; #else int flags; #endif struct sockaddr_in addr; if(!p) return NATPMP_ERR_INVALIDARGS; memset(p, 0, sizeof(natpmp_t)); p->s = socket(PF_INET, SOCK_DGRAM, 0); if(p->s < 0) return NATPMP_ERR_SOCKETERROR; #ifdef WIN32 if(ioctlsocket(p->s, FIONBIO, &ioctlArg) == SOCKET_ERROR) return NATPMP_ERR_FCNTLERROR; #else if((flags = fcntl(p->s, F_GETFL, 0)) < 0) return NATPMP_ERR_FCNTLERROR; if(fcntl(p->s, F_SETFL, flags | O_NONBLOCK) < 0) return NATPMP_ERR_FCNTLERROR; #endif if(forcegw) { p->gateway = forcedgw; } else { if(getdefaultgateway(&(p->gateway)) < 0) return NATPMP_ERR_CANNOTGETGATEWAY; } memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = htons(NATPMP_PORT); addr.sin_addr.s_addr = p->gateway; if(connect(p->s, (struct sockaddr *)&addr, sizeof(addr)) < 0) return NATPMP_ERR_CONNECTERR; return 0; } LIBSPEC int closenatpmp(natpmp_t * p) { if(!p) return NATPMP_ERR_INVALIDARGS; if(closesocket(p->s) < 0) return NATPMP_ERR_CLOSEERR; return 0; } int sendpendingrequest(natpmp_t * p) { int r; /* struct sockaddr_in addr;*/ if(!p) return NATPMP_ERR_INVALIDARGS; /* memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = htons(NATPMP_PORT); addr.sin_addr.s_addr = p->gateway; r = (int)sendto(p->s, p->pending_request, p->pending_request_len, 0, (struct sockaddr *)&addr, sizeof(addr));*/ r = (int)send(p->s, (const char *)p->pending_request, p->pending_request_len, 0); return (r<0) ? NATPMP_ERR_SENDERR : r; } int sendnatpmprequest(natpmp_t * p) { int n; if(!p) return NATPMP_ERR_INVALIDARGS; /* TODO : check if no request is already pending */ p->has_pending_request = 1; p->try_number = 1; n = sendpendingrequest(p); gettimeofday(&p->retry_time, NULL); // check errors ! p->retry_time.tv_usec += 250000; /* add 250ms */ if(p->retry_time.tv_usec >= 1000000) { p->retry_time.tv_usec -= 1000000; p->retry_time.tv_sec++; } return n; } LIBSPEC int getnatpmprequesttimeout(natpmp_t * p, struct timeval * timeout) { struct timeval now; if(!p || !timeout) return NATPMP_ERR_INVALIDARGS; if(!p->has_pending_request) return NATPMP_ERR_NOPENDINGREQ; if(gettimeofday(&now, NULL) < 0) return NATPMP_ERR_GETTIMEOFDAYERR; timeout->tv_sec = p->retry_time.tv_sec - now.tv_sec; timeout->tv_usec = p->retry_time.tv_usec - now.tv_usec; if(timeout->tv_usec < 0) { timeout->tv_usec += 1000000; timeout->tv_sec--; } return 0; } LIBSPEC int sendpublicaddressrequest(natpmp_t * p) { if(!p) return NATPMP_ERR_INVALIDARGS; //static const unsigned char request[] = { 0, 0 }; p->pending_request[0] = 0; p->pending_request[1] = 0; p->pending_request_len = 2; // TODO: return 0 instead of sizeof(request) ?? return sendnatpmprequest(p); } LIBSPEC int sendnewportmappingrequest(natpmp_t * p, int protocol, uint16_t privateport, uint16_t publicport, uint32_t lifetime) { if(!p || (protocol!=NATPMP_PROTOCOL_TCP && protocol!=NATPMP_PROTOCOL_UDP)) return NATPMP_ERR_INVALIDARGS; p->pending_request[0] = 0; p->pending_request[1] = protocol; p->pending_request[2] = 0; p->pending_request[3] = 0; /* break strict-aliasing rules : *((uint16_t *)(p->pending_request + 4)) = htons(privateport); */ p->pending_request[4] = (privateport >> 8) & 0xff; p->pending_request[5] = privateport & 0xff; /* break stric-aliasing rules : *((uint16_t *)(p->pending_request + 6)) = htons(publicport); */ p->pending_request[6] = (publicport >> 8) & 0xff; p->pending_request[7] = publicport & 0xff; /* break stric-aliasing rules : *((uint32_t *)(p->pending_request + 8)) = htonl(lifetime); */ p->pending_request[8] = (lifetime >> 24) & 0xff; p->pending_request[9] = (lifetime >> 16) & 0xff; p->pending_request[10] = (lifetime >> 8) & 0xff; p->pending_request[11] = lifetime & 0xff; p->pending_request_len = 12; return sendnatpmprequest(p); } LIBSPEC int readnatpmpresponse(natpmp_t * p, natpmpresp_t * response) { unsigned char buf[16]; struct sockaddr_in addr; socklen_t addrlen = sizeof(addr); int n; if(!p) return NATPMP_ERR_INVALIDARGS; n = recvfrom(p->s, (char *)buf, sizeof(buf), 0, (struct sockaddr *)&addr, &addrlen); if(n<0) #ifdef WIN32 switch(WSAGetLastError()) { #else switch(errno) { #endif /*case EAGAIN:*/ case EWOULDBLOCK: n = NATPMP_TRYAGAIN; break; case ECONNREFUSED: n = NATPMP_ERR_NOGATEWAYSUPPORT; break; default: n = NATPMP_ERR_RECVFROM; } /* check that addr is correct (= gateway) */ else if(addr.sin_addr.s_addr != p->gateway) n = NATPMP_ERR_WRONGPACKETSOURCE; else { response->resultcode = ntohs(*((uint16_t *)(buf + 2))); response->epoch = ntohl(*((uint32_t *)(buf + 4))); if(buf[0] != 0) n = NATPMP_ERR_UNSUPPORTEDVERSION; else if(buf[1] < 128 || buf[1] > 130) n = NATPMP_ERR_UNSUPPORTEDOPCODE; else if(response->resultcode != 0) { switch(response->resultcode) { case 1: n = NATPMP_ERR_UNSUPPORTEDVERSION; break; case 2: n = NATPMP_ERR_NOTAUTHORIZED; break; case 3: n = NATPMP_ERR_NETWORKFAILURE; break; case 4: n = NATPMP_ERR_OUTOFRESOURCES; break; case 5: n = NATPMP_ERR_UNSUPPORTEDOPCODE; break; default: n = NATPMP_ERR_UNDEFINEDERROR; } } else { response->type = buf[1] & 0x7f; if(buf[1] == 128) //response->publicaddress.addr = *((uint32_t *)(buf + 8)); response->pnu.publicaddress.addr.s_addr = *((uint32_t *)(buf + 8)); else { response->pnu.newportmapping.privateport = ntohs(*((uint16_t *)(buf + 8))); response->pnu.newportmapping.mappedpublicport = ntohs(*((uint16_t *)(buf + 10))); response->pnu.newportmapping.lifetime = ntohl(*((uint32_t *)(buf + 12))); } n = 0; } } return n; } int readnatpmpresponseorretry(natpmp_t * p, natpmpresp_t * response) { int n; if(!p || !response) return NATPMP_ERR_INVALIDARGS; if(!p->has_pending_request) return NATPMP_ERR_NOPENDINGREQ; n = readnatpmpresponse(p, response); if(n<0) { if(n==NATPMP_TRYAGAIN) { struct timeval now; gettimeofday(&now, NULL); // check errors ! if(timercmp(&now, &p->retry_time, >=)) { int delay, r; if(p->try_number >= 9) { return NATPMP_ERR_NOGATEWAYSUPPORT; } /*printf("retry! %d\n", p->try_number);*/ delay = 250 * (1<try_number); // ms /*for(i=0; itry_number; i++) delay += delay;*/ p->retry_time.tv_sec += (delay / 1000); p->retry_time.tv_usec += (delay % 1000) * 1000; if(p->retry_time.tv_usec >= 1000000) { p->retry_time.tv_usec -= 1000000; p->retry_time.tv_sec++; } p->try_number++; r = sendpendingrequest(p); if(r<0) return r; } } } else { p->has_pending_request = 0; } return n; } #ifdef ENABLE_STRNATPMPERR LIBSPEC const char * strnatpmperr(int r) { const char * s; switch(r) { case NATPMP_ERR_INVALIDARGS: s = "invalid arguments"; break; case NATPMP_ERR_SOCKETERROR: s = "socket() failed"; break; case NATPMP_ERR_CANNOTGETGATEWAY: s = "cannot get default gateway ip address"; break; case NATPMP_ERR_CLOSEERR: #ifdef WIN32 s = "closesocket() failed"; #else s = "close() failed"; #endif break; case NATPMP_ERR_RECVFROM: s = "recvfrom() failed"; break; case NATPMP_ERR_NOPENDINGREQ: s = "no pending request"; break; case NATPMP_ERR_NOGATEWAYSUPPORT: s = "the gateway does not support nat-pmp"; break; case NATPMP_ERR_CONNECTERR: s = "connect() failed"; break; case NATPMP_ERR_WRONGPACKETSOURCE: s = "packet not received from the default gateway"; break; case NATPMP_ERR_SENDERR: s = "send() failed"; break; case NATPMP_ERR_FCNTLERROR: s = "fcntl() failed"; break; case NATPMP_ERR_GETTIMEOFDAYERR: s = "gettimeofday() failed"; break; case NATPMP_ERR_UNSUPPORTEDVERSION: s = "unsupported nat-pmp version error from server"; break; case NATPMP_ERR_UNSUPPORTEDOPCODE: s = "unsupported nat-pmp opcode error from server"; break; case NATPMP_ERR_UNDEFINEDERROR: s = "undefined nat-pmp server error"; break; case NATPMP_ERR_NOTAUTHORIZED: s = "not authorized"; break; case NATPMP_ERR_NETWORKFAILURE: s = "network failure"; break; case NATPMP_ERR_OUTOFRESOURCES: s = "nat-pmp server out of resources"; break; default: s = "Unknown libnatpmp error"; } return s; } #endif opengnb-ver1.6.0.a/libs/libnatpmp/natpmp.h000066400000000000000000000162661500454252100205020ustar00rootroot00000000000000/* $Id: natpmp.h,v 1.20 2014/04/22 09:15:40 nanard Exp $ */ /* libnatpmp Copyright (c) 2007-2014, Thomas BERNARD All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * 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. * The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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. */ #ifndef __NATPMP_H__ #define __NATPMP_H__ /* NAT-PMP Port as defined by the NAT-PMP draft */ #define NATPMP_PORT (5351) #include #if !defined(_MSC_VER) #include #endif /* !defined(_MSC_VER) */ #ifdef WIN32 #include #if !defined(_MSC_VER) || _MSC_VER >= 1600 #include #else /* !defined(_MSC_VER) || _MSC_VER >= 1600 */ typedef unsigned long uint32_t; typedef unsigned short uint16_t; #endif /* !defined(_MSC_VER) || _MSC_VER >= 1600 */ #define in_addr_t uint32_t #include "declspec.h" #else /* WIN32 */ #define LIBSPEC #include #endif /* WIN32 */ /* causes problem when installing. Maybe should it be inlined ? */ /* #include "declspec.h" */ typedef struct { int s; /* socket */ in_addr_t gateway; /* default gateway (IPv4) */ int has_pending_request; unsigned char pending_request[12]; int pending_request_len; int try_number; struct timeval retry_time; } natpmp_t; typedef struct { uint16_t type; /* NATPMP_RESPTYPE_* */ uint16_t resultcode; /* NAT-PMP response code */ uint32_t epoch; /* Seconds since start of epoch */ union { struct { //in_addr_t addr; struct in_addr addr; } publicaddress; struct { uint16_t privateport; uint16_t mappedpublicport; uint32_t lifetime; } newportmapping; } pnu; } natpmpresp_t; /* possible values for type field of natpmpresp_t */ #define NATPMP_RESPTYPE_PUBLICADDRESS (0) #define NATPMP_RESPTYPE_UDPPORTMAPPING (1) #define NATPMP_RESPTYPE_TCPPORTMAPPING (2) /* Values to pass to sendnewportmappingrequest() */ #define NATPMP_PROTOCOL_UDP (1) #define NATPMP_PROTOCOL_TCP (2) /* return values */ /* NATPMP_ERR_INVALIDARGS : invalid arguments passed to the function */ #define NATPMP_ERR_INVALIDARGS (-1) /* NATPMP_ERR_SOCKETERROR : socket() failed. check errno for details */ #define NATPMP_ERR_SOCKETERROR (-2) /* NATPMP_ERR_CANNOTGETGATEWAY : can't get default gateway IP */ #define NATPMP_ERR_CANNOTGETGATEWAY (-3) /* NATPMP_ERR_CLOSEERR : close() failed. check errno for details */ #define NATPMP_ERR_CLOSEERR (-4) /* NATPMP_ERR_RECVFROM : recvfrom() failed. check errno for details */ #define NATPMP_ERR_RECVFROM (-5) /* NATPMP_ERR_NOPENDINGREQ : readnatpmpresponseorretry() called while * no NAT-PMP request was pending */ #define NATPMP_ERR_NOPENDINGREQ (-6) /* NATPMP_ERR_NOGATEWAYSUPPORT : the gateway does not support NAT-PMP */ #define NATPMP_ERR_NOGATEWAYSUPPORT (-7) /* NATPMP_ERR_CONNECTERR : connect() failed. check errno for details */ #define NATPMP_ERR_CONNECTERR (-8) /* NATPMP_ERR_WRONGPACKETSOURCE : packet not received from the network gateway */ #define NATPMP_ERR_WRONGPACKETSOURCE (-9) /* NATPMP_ERR_SENDERR : send() failed. check errno for details */ #define NATPMP_ERR_SENDERR (-10) /* NATPMP_ERR_FCNTLERROR : fcntl() failed. check errno for details */ #define NATPMP_ERR_FCNTLERROR (-11) /* NATPMP_ERR_GETTIMEOFDAYERR : gettimeofday() failed. check errno for details */ #define NATPMP_ERR_GETTIMEOFDAYERR (-12) /* */ #define NATPMP_ERR_UNSUPPORTEDVERSION (-14) #define NATPMP_ERR_UNSUPPORTEDOPCODE (-15) /* Errors from the server : */ #define NATPMP_ERR_UNDEFINEDERROR (-49) #define NATPMP_ERR_NOTAUTHORIZED (-51) #define NATPMP_ERR_NETWORKFAILURE (-52) #define NATPMP_ERR_OUTOFRESOURCES (-53) /* NATPMP_TRYAGAIN : no data available for the moment. try again later */ #define NATPMP_TRYAGAIN (-100) #ifdef __cplusplus extern "C" { #endif /* initnatpmp() * initialize a natpmp_t object * With forcegw=1 the gateway is not detected automaticaly. * Return values : * 0 = OK * NATPMP_ERR_INVALIDARGS * NATPMP_ERR_SOCKETERROR * NATPMP_ERR_FCNTLERROR * NATPMP_ERR_CANNOTGETGATEWAY * NATPMP_ERR_CONNECTERR */ LIBSPEC int initnatpmp(natpmp_t * p, int forcegw, in_addr_t forcedgw); /* closenatpmp() * close resources associated with a natpmp_t object * Return values : * 0 = OK * NATPMP_ERR_INVALIDARGS * NATPMP_ERR_CLOSEERR */ LIBSPEC int closenatpmp(natpmp_t * p); /* sendpublicaddressrequest() * send a public address NAT-PMP request to the network gateway * Return values : * 2 = OK (size of the request) * NATPMP_ERR_INVALIDARGS * NATPMP_ERR_SENDERR */ LIBSPEC int sendpublicaddressrequest(natpmp_t * p); /* sendnewportmappingrequest() * send a new port mapping NAT-PMP request to the network gateway * Arguments : * protocol is either NATPMP_PROTOCOL_TCP or NATPMP_PROTOCOL_UDP, * lifetime is in seconds. * To remove a port mapping, set lifetime to zero. * To remove all port mappings to the host, set lifetime and both ports * to zero. * Return values : * 12 = OK (size of the request) * NATPMP_ERR_INVALIDARGS * NATPMP_ERR_SENDERR */ LIBSPEC int sendnewportmappingrequest(natpmp_t * p, int protocol, uint16_t privateport, uint16_t publicport, uint32_t lifetime); /* getnatpmprequesttimeout() * fills the timeval structure with the timeout duration of the * currently pending NAT-PMP request. * Return values : * 0 = OK * NATPMP_ERR_INVALIDARGS * NATPMP_ERR_GETTIMEOFDAYERR * NATPMP_ERR_NOPENDINGREQ */ LIBSPEC int getnatpmprequesttimeout(natpmp_t * p, struct timeval * timeout); /* readnatpmpresponseorretry() * fills the natpmpresp_t structure if possible * Return values : * 0 = OK * NATPMP_TRYAGAIN * NATPMP_ERR_INVALIDARGS * NATPMP_ERR_NOPENDINGREQ * NATPMP_ERR_NOGATEWAYSUPPORT * NATPMP_ERR_RECVFROM * NATPMP_ERR_WRONGPACKETSOURCE * NATPMP_ERR_UNSUPPORTEDVERSION * NATPMP_ERR_UNSUPPORTEDOPCODE * NATPMP_ERR_NOTAUTHORIZED * NATPMP_ERR_NETWORKFAILURE * NATPMP_ERR_OUTOFRESOURCES * NATPMP_ERR_UNSUPPORTEDOPCODE * NATPMP_ERR_UNDEFINEDERROR */ LIBSPEC int readnatpmpresponseorretry(natpmp_t * p, natpmpresp_t * response); #ifdef ENABLE_STRNATPMPERR LIBSPEC const char * strnatpmperr(int t); #endif #ifdef __cplusplus } #endif #endif opengnb-ver1.6.0.a/libs/libnatpmp/wingettimeofday.c000066400000000000000000000042501500454252100223630ustar00rootroot00000000000000/* $Id: wingettimeofday.c,v 1.6 2013/09/10 20:13:26 nanard Exp $ */ /* libnatpmp Copyright (c) 2007-2013, Thomas BERNARD All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * 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. * The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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. */ #ifdef WIN32 #if defined(_MSC_VER) struct timeval { long tv_sec; long tv_usec; }; #else #include #endif typedef struct _FILETIME { unsigned long dwLowDateTime; unsigned long dwHighDateTime; } FILETIME; void __stdcall GetSystemTimeAsFileTime(FILETIME*); int natpmp_gettimeofday(struct timeval* p, void* tz /* IGNORED */) { union { long long ns100; /*time since 1 Jan 1601 in 100ns units */ FILETIME ft; } _now; if(!p) return -1; GetSystemTimeAsFileTime( &(_now.ft) ); p->tv_usec =(long)((_now.ns100 / 10LL) % 1000000LL ); p->tv_sec = (long)((_now.ns100-(116444736000000000LL))/10000000LL); return 0; } #endif opengnb-ver1.6.0.a/libs/libnatpmp/wingettimeofday.h000066400000000000000000000033671500454252100224000ustar00rootroot00000000000000/* $Id: wingettimeofday.h,v 1.5 2013/09/11 07:22:25 nanard Exp $ */ /* libnatpmp Copyright (c) 2007-2013, Thomas BERNARD All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * 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. * The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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. */ #ifndef __WINGETTIMEOFDAY_H__ #define __WINGETTIMEOFDAY_H__ #ifdef WIN32 #if defined(_MSC_VER) #include #else #include #endif int natpmp_gettimeofday(struct timeval* p, void* tz /* IGNORED */); #endif #endif opengnb-ver1.6.0.a/libs/miniupnpc/000077500000000000000000000000001500454252100170335ustar00rootroot00000000000000opengnb-ver1.6.0.a/libs/miniupnpc/LICENSE000066400000000000000000000027101500454252100200400ustar00rootroot00000000000000MiniUPnPc Copyright (c) 2005-2019, Thomas BERNARD All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * 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. * The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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. opengnb-ver1.6.0.a/libs/miniupnpc/README000066400000000000000000000066121500454252100177200ustar00rootroot00000000000000Project: miniupnp Project web page: http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/ github: https://github.com/miniupnp/miniupnp Author: Thomas Bernard Copyright (c) 2005-2019 Thomas Bernard This software is subject to the conditions detailed in the LICENSE file provided within this distribution. * miniUPnP Client - miniUPnPc * To compile, simply run 'gmake' (could be 'make' on your system). Under win32, to compile with MinGW, type "mingw32make.bat". MS Visual C solution and project files are supplied in the msvc/ subdirectory. The miniupnpc library is available as a static library or as a DLL : define MINIUPNP_STATICLIB if you want to link against the static library. The compilation is known to work under linux, FreeBSD, OpenBSD, MacOS X, AmigaOS and cygwin. The official AmigaOS4.1 SDK was used for AmigaOS4 and GeekGadgets for AmigaOS3. upx (http://upx.sourceforge.net) is used to compress the win32 .exe files. To install the library and headers on the system use : > su > make install > exit alternatively, to install into a specific location, use : > INSTALLPREFIX=/usr/local make install upnpc.c is a sample client using the libminiupnpc. To use the libminiupnpc in your application, link it with libminiupnpc.a (or .so) and use the following functions found in miniupnpc.h, upnpcommands.h and miniwget.h : - upnpDiscover() - UPNP_GetValidIGD() - miniwget() - parserootdesc() - GetUPNPUrls() - UPNP_* (calling UPNP methods) Note : use #include etc... for the includes and -lminiupnpc for the link Discovery process is speeded up when MiniSSDPd is running on the machine. * Python module * you can build a python module with 'make pythonmodule' and install it with 'make installpythonmodule'. setup.py (and setupmingw32.py) are included in the distribution. Feel free to contact me if you have any problem : e-mail : miniupnp@free.fr If you are using libminiupnpc in your application, please send me an email ! For any question, you can use the web forum : https://miniupnp.tuxfamily.org/forum/ Bugs should be reported on github : https://github.com/miniupnp/miniupnp/issues * Linux firewall configuration for UPnP clients * Due to how UPnP protocol is designed, unicast responses to UPnP multicast client requests are not tracked by Linux netfilter. And therefore netfilter executes default action for them (which is in most cases DROP response packet). To workaround this limitation, custom ipset hash table can be used. It is supported since Linux kernel >= 2.6.39. Rules for IPv4: $ ipset create upnp hash:ip,port timeout 3 $ iptables -A OUTPUT -d 239.255.255.250/32 -p udp -m udp --dport 1900 -j SET --add-set upnp src,src --exist $ iptables -A INPUT -p udp -m set --match-set upnp dst,dst -j ACCEPT $ iptables -A INPUT -d 239.255.255.250/32 -p udp -m udp --dport 1900 -j ACCEPT Rules for IPv6: $ ipset create upnp6 hash:ip,port timeout 3 family inet6 $ ip6tables -A OUTPUT -d ff02::c/128 -p udp -m udp --dport 1900 -j SET --add-set upnp6 src,src --exist $ ip6tables -A OUTPUT -d ff05::c/128 -p udp -m udp --dport 1900 -j SET --add-set upnp6 src,src --exist $ ip6tables -A INPUT -p udp -m set --match-set upnp6 dst,dst -j ACCEPT $ ip6tables -A INPUT -d ff02::c/128 -p udp -m udp --dport 1900 -j ACCEPT $ ip6tables -A INPUT -d ff05::c/128 -p udp -m udp --dport 1900 -j ACCEPT Detailed description is available on: https://serverfault.com/a/911286 https://unix.stackexchange.com/a/444804 opengnb-ver1.6.0.a/libs/miniupnpc/VERSION000066400000000000000000000000041500454252100200750ustar00rootroot000000000000002.1 opengnb-ver1.6.0.a/libs/miniupnpc/codelength.h000066400000000000000000000030251500454252100213200ustar00rootroot00000000000000/* $Id: codelength.h,v 1.5 2015/07/09 12:40:18 nanard Exp $ */ /* Project : miniupnp * Author : Thomas BERNARD * copyright (c) 2005-2015 Thomas Bernard * This software is subjet to the conditions detailed in the * provided LICENCE file. */ #ifndef CODELENGTH_H_INCLUDED #define CODELENGTH_H_INCLUDED /* Encode length by using 7bit per Byte : * Most significant bit of each byte specifies that the * following byte is part of the code */ /* n : unsigned * p : unsigned char * */ #define DECODELENGTH(n, p) n = 0; \ do { n = (n << 7) | (*p & 0x7f); } \ while((*(p++)&0x80) && (n<(1<<25))); /* n : unsigned * READ : function/macro to read one byte (unsigned char) */ #define DECODELENGTH_READ(n, READ) \ n = 0; \ do { \ unsigned char c; \ READ(c); \ n = (n << 7) | (c & 0x07f); \ if(!(c&0x80)) break; \ } while(n<(1<<25)); /* n : unsigned * p : unsigned char * * p_limit : unsigned char * */ #define DECODELENGTH_CHECKLIMIT(n, p, p_limit) \ n = 0; \ do { \ if((p) >= (p_limit)) break; \ n = (n << 7) | (*(p) & 0x7f); \ } while((*((p)++)&0x80) && (n<(1<<25))); /* n : unsigned * p : unsigned char * */ #define CODELENGTH(n, p) if(n>=268435456) *(p++) = (n >> 28) | 0x80; \ if(n>=2097152) *(p++) = (n >> 21) | 0x80; \ if(n>=16384) *(p++) = (n >> 14) | 0x80; \ if(n>=128) *(p++) = (n >> 7) | 0x80; \ *(p++) = n & 0x7f; #endif /* CODELENGTH_H_INCLUDED */ opengnb-ver1.6.0.a/libs/miniupnpc/connecthostport.c000066400000000000000000000166071500454252100224450ustar00rootroot00000000000000/* $Id: connecthostport.c,v 1.22 2019/10/13 17:22:08 nanard Exp $ */ /* vim: tabstop=4 shiftwidth=4 noexpandtab * Project : miniupnp * Author : Thomas Bernard * Copyright (c) 2010-2019 Thomas Bernard * This software is subject to the conditions detailed in the * LICENCE file provided in this distribution. */ /* use getaddrinfo() or gethostbyname() * uncomment the following line in order to use gethostbyname() */ #ifdef NO_GETADDRINFO #define USE_GETHOSTBYNAME #endif #include #include #ifdef _WIN32 #include #include #include #define MAXHOSTNAMELEN 64 #define snprintf _snprintf #define herror #define socklen_t int #else /* #ifdef _WIN32 */ #include #include #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT #include #endif /* #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT */ #include #include #include #define closesocket close #include #include /* defining MINIUPNPC_IGNORE_EINTR enable the ignore of interruptions * during the connect() call */ #define MINIUPNPC_IGNORE_EINTR #include #include #endif /* #else _WIN32 */ #if defined(__amigaos__) || defined(__amigaos4__) #define herror(A) printf("%s\n", A) #endif #include "connecthostport.h" #ifndef MAXHOSTNAMELEN #define MAXHOSTNAMELEN 64 #endif /* connecthostport() * return a socket connected (TCP) to the host and port * or -1 in case of error */ SOCKET connecthostport(const char * host, unsigned short port, unsigned int scope_id) { SOCKET s; int n; #ifdef USE_GETHOSTBYNAME struct sockaddr_in dest; struct hostent *hp; #else /* #ifdef USE_GETHOSTBYNAME */ char tmp_host[MAXHOSTNAMELEN+1]; char port_str[8]; struct addrinfo *ai, *p; struct addrinfo hints; #endif /* #ifdef USE_GETHOSTBYNAME */ #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT struct timeval timeout; #endif /* #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT */ #ifdef USE_GETHOSTBYNAME hp = gethostbyname(host); if(hp == NULL) { herror(host); return INVALID_SOCKET; } memcpy(&dest.sin_addr, hp->h_addr, sizeof(dest.sin_addr)); memset(dest.sin_zero, 0, sizeof(dest.sin_zero)); s = socket(PF_INET, SOCK_STREAM, 0); if(ISINVALID(s)) { PRINT_SOCKET_ERROR("socket"); return INVALID_SOCKET; } #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT /* setting a 3 seconds timeout for the connect() call */ timeout.tv_sec = 3; timeout.tv_usec = 0; if(setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(struct timeval)) < 0) { PRINT_SOCKET_ERROR("setsockopt SO_RCVTIMEO"); } timeout.tv_sec = 3; timeout.tv_usec = 0; if(setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(struct timeval)) < 0) { PRINT_SOCKET_ERROR("setsockopt SO_SNDTIMEO"); } #endif /* #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT */ dest.sin_family = AF_INET; dest.sin_port = htons(port); n = connect(s, (struct sockaddr *)&dest, sizeof(struct sockaddr_in)); #ifdef MINIUPNPC_IGNORE_EINTR /* EINTR The system call was interrupted by a signal that was caught * EINPROGRESS The socket is nonblocking and the connection cannot * be completed immediately. */ while(n < 0 && (errno == EINTR || errno == EINPROGRESS)) { socklen_t len; fd_set wset; int err; FD_ZERO(&wset); FD_SET(s, &wset); #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT timeout.tv_sec = 3; timeout.tv_usec = 0; n = select(s + 1, NULL, &wset, NULL, &timeout); #else n = select(s + 1, NULL, &wset, NULL, NULL); #endif if(n == -1 && errno == EINTR) continue; #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT if(n == 0) { errno = ETIMEDOUT; n = -1; break; } #endif /*len = 0;*/ /*n = getpeername(s, NULL, &len);*/ len = sizeof(err); if(getsockopt(s, SOL_SOCKET, SO_ERROR, &err, &len) < 0) { PRINT_SOCKET_ERROR("getsockopt"); closesocket(s); return INVALID_SOCKET; } if(err != 0) { errno = err; n = -1; } } #endif /* #ifdef MINIUPNPC_IGNORE_EINTR */ if(n<0) { PRINT_SOCKET_ERROR("connect"); closesocket(s); return INVALID_SOCKET; } #else /* #ifdef USE_GETHOSTBYNAME */ /* use getaddrinfo() instead of gethostbyname() */ memset(&hints, 0, sizeof(hints)); /* hints.ai_flags = AI_ADDRCONFIG; */ #ifdef AI_NUMERICSERV hints.ai_flags = AI_NUMERICSERV; #endif hints.ai_socktype = SOCK_STREAM; hints.ai_family = AF_UNSPEC; /* AF_INET, AF_INET6 or AF_UNSPEC */ /* hints.ai_protocol = IPPROTO_TCP; */ snprintf(port_str, sizeof(port_str), "%hu", port); if(host[0] == '[') { /* literal ip v6 address */ int i, j; for(i = 0, j = 1; host[j] && (host[j] != ']') && i < MAXHOSTNAMELEN; i++, j++) { tmp_host[i] = host[j]; if(0 == strncmp(host+j, "%25", 3)) /* %25 is just url encoding for '%' */ j+=2; /* skip "25" */ } tmp_host[i] = '\0'; } else { strncpy(tmp_host, host, MAXHOSTNAMELEN); } tmp_host[MAXHOSTNAMELEN] = '\0'; n = getaddrinfo(tmp_host, port_str, &hints, &ai); if(n != 0) { #ifdef _WIN32 fprintf(stderr, "getaddrinfo() error : %d\n", n); #else fprintf(stderr, "getaddrinfo() error : %s\n", gai_strerror(n)); #endif return INVALID_SOCKET; } s = INVALID_SOCKET; for(p = ai; p; p = p->ai_next) { if(!ISINVALID(s)) closesocket(s); #ifdef DEBUG printf("ai_family=%d ai_socktype=%d ai_protocol=%d (PF_INET=%d, PF_INET6=%d)\n", p->ai_family, p->ai_socktype, p->ai_protocol, PF_INET, PF_INET6); #endif s = socket(p->ai_family, p->ai_socktype, p->ai_protocol); if(ISINVALID(s)) continue; if(p->ai_addr->sa_family == AF_INET6 && scope_id > 0) { struct sockaddr_in6 * addr6 = (struct sockaddr_in6 *)p->ai_addr; addr6->sin6_scope_id = scope_id; } #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT /* setting a 3 seconds timeout for the connect() call */ timeout.tv_sec = 3; timeout.tv_usec = 0; if(setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(struct timeval)) < 0) { PRINT_SOCKET_ERROR("setsockopt"); } timeout.tv_sec = 3; timeout.tv_usec = 0; if(setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(struct timeval)) < 0) { PRINT_SOCKET_ERROR("setsockopt"); } #endif /* #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT */ n = connect(s, p->ai_addr, MSC_CAST_INT p->ai_addrlen); #ifdef MINIUPNPC_IGNORE_EINTR /* EINTR The system call was interrupted by a signal that was caught * EINPROGRESS The socket is nonblocking and the connection cannot * be completed immediately. */ while(n < 0 && (errno == EINTR || errno == EINPROGRESS)) { socklen_t len; fd_set wset; int err; FD_ZERO(&wset); FD_SET(s, &wset); #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT timeout.tv_sec = 3; timeout.tv_usec = 0; n = select(s + 1, NULL, &wset, NULL, &timeout); #else n = select(s + 1, NULL, &wset, NULL, NULL); #endif if(n == -1 && errno == EINTR) continue; #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT if(n == 0) { errno = ETIMEDOUT; n = -1; break; } #endif /*len = 0;*/ /*n = getpeername(s, NULL, &len);*/ len = sizeof(err); if(getsockopt(s, SOL_SOCKET, SO_ERROR, &err, &len) < 0) { PRINT_SOCKET_ERROR("getsockopt"); closesocket(s); freeaddrinfo(ai); return INVALID_SOCKET; } if(err != 0) { errno = err; n = -1; } } #endif /* #ifdef MINIUPNPC_IGNORE_EINTR */ if(n >= 0) /* connect() was successful */ break; } freeaddrinfo(ai); if(ISINVALID(s)) { PRINT_SOCKET_ERROR("socket"); return INVALID_SOCKET; } if(n < 0) { PRINT_SOCKET_ERROR("connect"); closesocket(s); return INVALID_SOCKET; } #endif /* #ifdef USE_GETHOSTBYNAME */ return s; } opengnb-ver1.6.0.a/libs/miniupnpc/connecthostport.h000066400000000000000000000012031500454252100224340ustar00rootroot00000000000000/* $Id: connecthostport.h,v 1.4 2018/04/06 10:53:13 nanard Exp $ */ /* Project: miniupnp * http://miniupnp.free.fr/ * Author: Thomas Bernard * Copyright (c) 2010-2018 Thomas Bernard * This software is subjects to the conditions detailed * in the LICENCE file provided within this distribution */ #ifndef CONNECTHOSTPORT_H_INCLUDED #define CONNECTHOSTPORT_H_INCLUDED #include "miniupnpc_socketdef.h" /* connecthostport() * return a socket connected (TCP) to the host and port * or INVALID_SOCKET in case of error */ SOCKET connecthostport(const char * host, unsigned short port, unsigned int scope_id); #endif opengnb-ver1.6.0.a/libs/miniupnpc/igd_desc_parse.c000066400000000000000000000110161500454252100221310ustar00rootroot00000000000000/* $Id: igd_desc_parse.c,v 1.17 2015/09/15 13:30:04 nanard Exp $ */ /* Project : miniupnp * http://miniupnp.free.fr/ * Author : Thomas Bernard * Copyright (c) 2005-2015 Thomas Bernard * This software is subject to the conditions detailed in the * LICENCE file provided in this distribution. */ #include "igd_desc_parse.h" #include #include /* Start element handler : * update nesting level counter and copy element name */ void IGDstartelt(void * d, const char * name, int l) { struct IGDdatas * datas = (struct IGDdatas *)d; if(l >= MINIUPNPC_URL_MAXSIZE) l = MINIUPNPC_URL_MAXSIZE-1; memcpy(datas->cureltname, name, l); datas->cureltname[l] = '\0'; datas->level++; if( (l==7) && !memcmp(name, "service", l) ) { datas->tmp.controlurl[0] = '\0'; datas->tmp.eventsuburl[0] = '\0'; datas->tmp.scpdurl[0] = '\0'; datas->tmp.servicetype[0] = '\0'; } } #define COMPARE(str, cstr) (0==memcmp(str, cstr, sizeof(cstr) - 1)) /* End element handler : * update nesting level counter and update parser state if * service element is parsed */ void IGDendelt(void * d, const char * name, int l) { struct IGDdatas * datas = (struct IGDdatas *)d; datas->level--; /*printf("endelt %2d %.*s\n", datas->level, l, name);*/ if( (l==7) && !memcmp(name, "service", l) ) { if(COMPARE(datas->tmp.servicetype, "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:")) { memcpy(&datas->CIF, &datas->tmp, sizeof(struct IGDdatas_service)); } else if(COMPARE(datas->tmp.servicetype, "urn:schemas-upnp-org:service:WANIPv6FirewallControl:")) { memcpy(&datas->IPv6FC, &datas->tmp, sizeof(struct IGDdatas_service)); } else if(COMPARE(datas->tmp.servicetype, "urn:schemas-upnp-org:service:WANIPConnection:") || COMPARE(datas->tmp.servicetype, "urn:schemas-upnp-org:service:WANPPPConnection:") ) { if(datas->first.servicetype[0] == '\0') { memcpy(&datas->first, &datas->tmp, sizeof(struct IGDdatas_service)); } else { memcpy(&datas->second, &datas->tmp, sizeof(struct IGDdatas_service)); } } } } /* Data handler : * copy data depending on the current element name and state */ void IGDdata(void * d, const char * data, int l) { struct IGDdatas * datas = (struct IGDdatas *)d; char * dstmember = 0; /*printf("%2d %s : %.*s\n", datas->level, datas->cureltname, l, data); */ if( !strcmp(datas->cureltname, "URLBase") ) dstmember = datas->urlbase; else if( !strcmp(datas->cureltname, "presentationURL") ) dstmember = datas->presentationurl; else if( !strcmp(datas->cureltname, "serviceType") ) dstmember = datas->tmp.servicetype; else if( !strcmp(datas->cureltname, "controlURL") ) dstmember = datas->tmp.controlurl; else if( !strcmp(datas->cureltname, "eventSubURL") ) dstmember = datas->tmp.eventsuburl; else if( !strcmp(datas->cureltname, "SCPDURL") ) dstmember = datas->tmp.scpdurl; /* else if( !strcmp(datas->cureltname, "deviceType") ) dstmember = datas->devicetype_tmp;*/ if(dstmember) { if(l>=MINIUPNPC_URL_MAXSIZE) l = MINIUPNPC_URL_MAXSIZE-1; memcpy(dstmember, data, l); dstmember[l] = '\0'; } } #ifdef DEBUG void printIGD(struct IGDdatas * d) { printf("urlbase = '%s'\n", d->urlbase); printf("WAN Device (Common interface config) :\n"); /*printf(" deviceType = '%s'\n", d->CIF.devicetype);*/ printf(" serviceType = '%s'\n", d->CIF.servicetype); printf(" controlURL = '%s'\n", d->CIF.controlurl); printf(" eventSubURL = '%s'\n", d->CIF.eventsuburl); printf(" SCPDURL = '%s'\n", d->CIF.scpdurl); printf("primary WAN Connection Device (IP or PPP Connection):\n"); /*printf(" deviceType = '%s'\n", d->first.devicetype);*/ printf(" servicetype = '%s'\n", d->first.servicetype); printf(" controlURL = '%s'\n", d->first.controlurl); printf(" eventSubURL = '%s'\n", d->first.eventsuburl); printf(" SCPDURL = '%s'\n", d->first.scpdurl); printf("secondary WAN Connection Device (IP or PPP Connection):\n"); /*printf(" deviceType = '%s'\n", d->second.devicetype);*/ printf(" servicetype = '%s'\n", d->second.servicetype); printf(" controlURL = '%s'\n", d->second.controlurl); printf(" eventSubURL = '%s'\n", d->second.eventsuburl); printf(" SCPDURL = '%s'\n", d->second.scpdurl); printf("WAN IPv6 Firewall Control :\n"); /*printf(" deviceType = '%s'\n", d->IPv6FC.devicetype);*/ printf(" servicetype = '%s'\n", d->IPv6FC.servicetype); printf(" controlURL = '%s'\n", d->IPv6FC.controlurl); printf(" eventSubURL = '%s'\n", d->IPv6FC.eventsuburl); printf(" SCPDURL = '%s'\n", d->IPv6FC.scpdurl); } #endif /* DEBUG */ opengnb-ver1.6.0.a/libs/miniupnpc/igd_desc_parse.h000066400000000000000000000031351500454252100221410ustar00rootroot00000000000000/* $Id: igd_desc_parse.h,v 1.12 2014/11/17 17:19:13 nanard Exp $ */ /* Project : miniupnp * http://miniupnp.free.fr/ * Author : Thomas Bernard * Copyright (c) 2005-2014 Thomas Bernard * This software is subject to the conditions detailed in the * LICENCE file provided in this distribution. * */ #ifndef IGD_DESC_PARSE_H_INCLUDED #define IGD_DESC_PARSE_H_INCLUDED /* Structure to store the result of the parsing of UPnP * descriptions of Internet Gateway Devices */ #define MINIUPNPC_URL_MAXSIZE (128) struct IGDdatas_service { char controlurl[MINIUPNPC_URL_MAXSIZE]; char eventsuburl[MINIUPNPC_URL_MAXSIZE]; char scpdurl[MINIUPNPC_URL_MAXSIZE]; char servicetype[MINIUPNPC_URL_MAXSIZE]; /*char devicetype[MINIUPNPC_URL_MAXSIZE];*/ }; struct IGDdatas { char cureltname[MINIUPNPC_URL_MAXSIZE]; char urlbase[MINIUPNPC_URL_MAXSIZE]; char presentationurl[MINIUPNPC_URL_MAXSIZE]; int level; /*int state;*/ /* "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1" */ struct IGDdatas_service CIF; /* "urn:schemas-upnp-org:service:WANIPConnection:1" * "urn:schemas-upnp-org:service:WANPPPConnection:1" */ struct IGDdatas_service first; /* if both WANIPConnection and WANPPPConnection are present */ struct IGDdatas_service second; /* "urn:schemas-upnp-org:service:WANIPv6FirewallControl:1" */ struct IGDdatas_service IPv6FC; /* tmp */ struct IGDdatas_service tmp; }; void IGDstartelt(void *, const char *, int); void IGDendelt(void *, const char *, int); void IGDdata(void *, const char *, int); #ifdef DEBUG void printIGD(struct IGDdatas *); #endif /* DEBUG */ #endif /* IGD_DESC_PARSE_H_INCLUDED */ opengnb-ver1.6.0.a/libs/miniupnpc/minisoap.c000066400000000000000000000067021500454252100210230ustar00rootroot00000000000000/* $Id: minisoap.c,v 1.28 2019/02/10 12:29:23 nanard Exp $ */ /* vim: tabstop=4 shiftwidth=4 noexpandtab * Project : miniupnp * Author : Thomas Bernard * Copyright (c) 2005-2018 Thomas Bernard * This software is subject to the conditions detailed in the * LICENCE file provided in this distribution. * * Minimal SOAP implementation for UPnP protocol. */ #include #include #ifdef _WIN32 #include #include #define snprintf _snprintf #else #include #include #include #endif #include "minisoap.h" #include "miniupnpcstrings.h" /* only for malloc */ #include /* httpWrite sends the headers and the body to the socket * and returns the number of bytes sent */ static int httpWrite(SOCKET fd, const char * body, int bodysize, const char * headers, int headerssize) { int n = 0; /*n = write(fd, headers, headerssize);*/ /*if(bodysize>0) n += write(fd, body, bodysize);*/ /* Note : my old linksys router only took into account * soap request that are sent into only one packet */ char * p; /* TODO: AVOID MALLOC, we could use writev() for that */ p = malloc(headerssize+bodysize); if(!p) return -1; memcpy(p, headers, headerssize); memcpy(p+headerssize, body, bodysize); /*n = write(fd, p, headerssize+bodysize);*/ n = send(fd, p, headerssize+bodysize, 0); if(n<0) { PRINT_SOCKET_ERROR("send"); } /* disable send on the socket */ /* draytek routers don't seem to like that... */ #if 0 #ifdef _WIN32 if(shutdown(fd, SD_SEND)<0) { #else if(shutdown(fd, SHUT_WR)<0) { /*SD_SEND*/ #endif PRINT_SOCKET_ERROR("shutdown"); } #endif free(p); return n; } /* self explanatory */ int soapPostSubmit(SOCKET fd, const char * url, const char * host, unsigned short port, const char * action, const char * body, const char * httpversion) { char headerbuf[512]; int headerssize; char portstr[8]; int bodysize = (int)strlen(body); /* We are not using keep-alive HTTP connections. * HTTP/1.1 needs the header Connection: close to do that. * This is the default with HTTP/1.0 * Using HTTP/1.1 means we need to support chunked transfer-encoding : * When using HTTP/1.1, the router "BiPAC 7404VNOX" always use chunked * transfer encoding. */ /* Connection: Close is normally there only in HTTP/1.1 but who knows */ portstr[0] = '\0'; if(port != 80) snprintf(portstr, sizeof(portstr), ":%hu", port); headerssize = snprintf(headerbuf, sizeof(headerbuf), "POST %s HTTP/%s\r\n" "Host: %s%s\r\n" "User-Agent: " OS_STRING ", " UPNP_VERSION_STRING ", MiniUPnPc/" MINIUPNPC_VERSION_STRING "\r\n" "Content-Length: %d\r\n" "Content-Type: text/xml\r\n" "SOAPAction: \"%s\"\r\n" "Connection: Close\r\n" "Cache-Control: no-cache\r\n" /* ??? */ "Pragma: no-cache\r\n" "\r\n", url, httpversion, host, portstr, bodysize, action); if ((unsigned int)headerssize >= sizeof(headerbuf)) return -1; #ifdef DEBUG /*printf("SOAP request : headersize=%d bodysize=%d\n", headerssize, bodysize); */ printf("SOAP request : POST %s HTTP/%s - Host: %s%s\n", url, httpversion, host, portstr); printf("SOAPAction: \"%s\" - Content-Length: %d\n", action, bodysize); printf("Headers :\n%s", headerbuf); printf("Body :\n%s\n", body); #endif return httpWrite(fd, body, bodysize, headerbuf, headerssize); } opengnb-ver1.6.0.a/libs/miniupnpc/minisoap.h000066400000000000000000000010341500454252100210210ustar00rootroot00000000000000/* $Id: minisoap.h,v 1.6 2018/04/06 10:53:13 nanard Exp $ */ /* Project : miniupnp * Author : Thomas Bernard * Copyright (c) 2005-2018 Thomas Bernard * This software is subject to the conditions detailed in the * LICENCE file provided in this distribution. */ #ifndef MINISOAP_H_INCLUDED #define MINISOAP_H_INCLUDED #include "miniupnpc_socketdef.h" /*int httpWrite(int, const char *, int, const char *);*/ int soapPostSubmit(SOCKET, const char *, const char *, unsigned short, const char *, const char *, const char *); #endif opengnb-ver1.6.0.a/libs/miniupnpc/minissdpc.c000066400000000000000000000626511500454252100212020ustar00rootroot00000000000000/* $Id: minissdpc.c,v 1.41 2019/06/25 21:20:09 nanard Exp $ */ /* vim: tabstop=4 shiftwidth=4 noexpandtab * Project : miniupnp * Web : http://miniupnp.free.fr/ * Author : Thomas BERNARD * copyright (c) 2005-2019 Thomas Bernard * This software is subjet to the conditions detailed in the * provided LICENCE file. */ /*#include */ #include #include #include #include #if defined (__NetBSD__) #include #endif #if defined(_WIN32) || defined(__amigaos__) || defined(__amigaos4__) #ifdef _WIN32 #include #include #include #include #define snprintf _snprintf #if !defined(_MSC_VER) #include #else /* !defined(_MSC_VER) */ typedef unsigned short uint16_t; #endif /* !defined(_MSC_VER) */ #ifndef strncasecmp #if defined(_MSC_VER) && (_MSC_VER >= 1400) #define strncasecmp _memicmp #else /* defined(_MSC_VER) && (_MSC_VER >= 1400) */ #define strncasecmp memicmp #endif /* defined(_MSC_VER) && (_MSC_VER >= 1400) */ #endif /* #ifndef strncasecmp */ #endif /* _WIN32 */ #if defined(__amigaos__) || defined(__amigaos4__) #include #endif /* defined(__amigaos__) || defined(__amigaos4__) */ #if defined(__amigaos__) #define uint16_t unsigned short #endif /* defined(__amigaos__) */ /* Hack */ #define UNIX_PATH_LEN 108 struct sockaddr_un { uint16_t sun_family; char sun_path[UNIX_PATH_LEN]; }; #else /* defined(_WIN32) || defined(__amigaos__) || defined(__amigaos4__) */ #include #include #include #include #include #include #include #include #include #include #define closesocket close #endif #include "miniupnpc_socketdef.h" #if !defined(__DragonFly__) && !defined(__OpenBSD__) && !defined(__NetBSD__) && !defined(__APPLE__) && !defined(_WIN32) && !defined(__CYGWIN__) && !defined(__sun) && !defined(__GNU__) && !defined(__FreeBSD_kernel__) #define HAS_IP_MREQN #endif #if !defined(HAS_IP_MREQN) && !defined(_WIN32) #include #if defined(__sun) #include #endif #endif #if defined(HAS_IP_MREQN) && defined(NEED_STRUCT_IP_MREQN) /* Several versions of glibc don't define this structure, * define it here and compile with CFLAGS NEED_STRUCT_IP_MREQN */ struct ip_mreqn { struct in_addr imr_multiaddr; /* IP multicast address of group */ struct in_addr imr_address; /* local IP address of interface */ int imr_ifindex; /* Interface index */ }; #endif #if defined(__amigaos__) || defined(__amigaos4__) /* Amiga OS specific stuff */ #define TIMEVAL struct timeval #endif #include "minissdpc.h" #include "miniupnpc.h" #include "receivedata.h" #if !(defined(_WIN32) || defined(__amigaos__) || defined(__amigaos4__)) #include "codelength.h" struct UPNPDev * getDevicesFromMiniSSDPD(const char * devtype, const char * socketpath, int * error) { struct UPNPDev * devlist = NULL; int s; int res; s = connectToMiniSSDPD(socketpath); if (s < 0) { if (error) *error = s; return NULL; } res = requestDevicesFromMiniSSDPD(s, devtype); if (res < 0) { if (error) *error = res; } else { devlist = receiveDevicesFromMiniSSDPD(s, error); } disconnectFromMiniSSDPD(s); return devlist; } /* macros used to read from unix socket */ #define READ_BYTE_BUFFER(c) \ if((int)bufferindex >= n) { \ n = read(s, buffer, sizeof(buffer)); \ if(n<=0) break; \ bufferindex = 0; \ } \ c = buffer[bufferindex++]; #ifndef MIN #define MIN(a, b) (((a) < (b)) ? (a) : (b)) #endif /* MIN */ #define READ_COPY_BUFFER(dst, len) \ for(l = len, p = (unsigned char *)dst; l > 0; ) { \ unsigned int lcopy; \ if((int)bufferindex >= n) { \ n = read(s, buffer, sizeof(buffer)); \ if(n<=0) break; \ bufferindex = 0; \ } \ lcopy = MIN(l, (n - bufferindex)); \ memcpy(p, buffer + bufferindex, lcopy); \ l -= lcopy; \ p += lcopy; \ bufferindex += lcopy; \ } #define READ_DISCARD_BUFFER(len) \ for(l = len; l > 0; ) { \ unsigned int lcopy; \ if(bufferindex >= n) { \ n = read(s, buffer, sizeof(buffer)); \ if(n<=0) break; \ bufferindex = 0; \ } \ lcopy = MIN(l, (n - bufferindex)); \ l -= lcopy; \ bufferindex += lcopy; \ } int connectToMiniSSDPD(const char * socketpath) { int s; struct sockaddr_un addr; #if defined(MINIUPNPC_SET_SOCKET_TIMEOUT) && !defined(__sun) struct timeval timeout; #endif /* #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT */ s = socket(AF_UNIX, SOCK_STREAM, 0); if(s < 0) { /*syslog(LOG_ERR, "socket(unix): %m");*/ perror("socket(unix)"); return MINISSDPC_SOCKET_ERROR; } #if defined(MINIUPNPC_SET_SOCKET_TIMEOUT) && !defined(__sun) /* setting a 3 seconds timeout */ /* not supported for AF_UNIX sockets under Solaris */ timeout.tv_sec = 3; timeout.tv_usec = 0; if(setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(struct timeval)) < 0) { perror("setsockopt SO_RCVTIMEO unix"); } timeout.tv_sec = 3; timeout.tv_usec = 0; if(setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(struct timeval)) < 0) { perror("setsockopt SO_SNDTIMEO unix"); } #endif /* #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT */ if(!socketpath) socketpath = "/var/run/minissdpd.sock"; memset(&addr, 0, sizeof(addr)); addr.sun_family = AF_UNIX; strncpy(addr.sun_path, socketpath, sizeof(addr.sun_path)); /* TODO : check if we need to handle the EINTR */ if(connect(s, (struct sockaddr *)&addr, sizeof(struct sockaddr_un)) < 0) { /*syslog(LOG_WARNING, "connect(\"%s\"): %m", socketpath);*/ close(s); return MINISSDPC_SOCKET_ERROR; } return s; } int disconnectFromMiniSSDPD(int s) { if (close(s) < 0) return MINISSDPC_SOCKET_ERROR; return MINISSDPC_SUCCESS; } int requestDevicesFromMiniSSDPD(int s, const char * devtype) { unsigned char buffer[256]; unsigned char * p; unsigned int stsize, l; stsize = strlen(devtype); if(stsize == 8 && 0 == memcmp(devtype, "ssdp:all", 8)) { buffer[0] = 3; /* request type 3 : everything */ } else { buffer[0] = 1; /* request type 1 : request devices/services by type */ } p = buffer + 1; l = stsize; CODELENGTH(l, p); if(p + stsize > buffer + sizeof(buffer)) { /* devtype is too long ! */ #ifdef DEBUG fprintf(stderr, "devtype is too long ! stsize=%u sizeof(buffer)=%u\n", stsize, (unsigned)sizeof(buffer)); #endif /* DEBUG */ return MINISSDPC_INVALID_INPUT; } memcpy(p, devtype, stsize); p += stsize; if(write(s, buffer, p - buffer) < 0) { /*syslog(LOG_ERR, "write(): %m");*/ perror("minissdpc.c: write()"); return MINISSDPC_SOCKET_ERROR; } return MINISSDPC_SUCCESS; } struct UPNPDev * receiveDevicesFromMiniSSDPD(int s, int * error) { struct UPNPDev * tmp; struct UPNPDev * devlist = NULL; unsigned char buffer[256]; ssize_t n; unsigned char * p; unsigned char * url; unsigned char * st; unsigned int bufferindex; unsigned int i, ndev; unsigned int urlsize, stsize, usnsize, l; n = read(s, buffer, sizeof(buffer)); if(n<=0) { perror("minissdpc.c: read()"); if (error) *error = MINISSDPC_SOCKET_ERROR; return NULL; } ndev = buffer[0]; bufferindex = 1; for(i = 0; i < ndev; i++) { DECODELENGTH_READ(urlsize, READ_BYTE_BUFFER); if(n<=0) { if (error) *error = MINISSDPC_INVALID_SERVER_REPLY; return devlist; } #ifdef DEBUG printf(" urlsize=%u", urlsize); #endif /* DEBUG */ url = malloc(urlsize); if(url == NULL) { if (error) *error = MINISSDPC_MEMORY_ERROR; return devlist; } READ_COPY_BUFFER(url, urlsize); if(n<=0) { if (error) *error = MINISSDPC_INVALID_SERVER_REPLY; goto free_url_and_return; } DECODELENGTH_READ(stsize, READ_BYTE_BUFFER); if(n<=0) { if (error) *error = MINISSDPC_INVALID_SERVER_REPLY; goto free_url_and_return; } #ifdef DEBUG printf(" stsize=%u", stsize); #endif /* DEBUG */ st = malloc(stsize); if (st == NULL) { if (error) *error = MINISSDPC_MEMORY_ERROR; goto free_url_and_return; } READ_COPY_BUFFER(st, stsize); if(n<=0) { if (error) *error = MINISSDPC_INVALID_SERVER_REPLY; goto free_url_and_st_and_return; } DECODELENGTH_READ(usnsize, READ_BYTE_BUFFER); if(n<=0) { if (error) *error = MINISSDPC_INVALID_SERVER_REPLY; goto free_url_and_st_and_return; } #ifdef DEBUG printf(" usnsize=%u\n", usnsize); #endif /* DEBUG */ tmp = (struct UPNPDev *)malloc(sizeof(struct UPNPDev)+urlsize+stsize+usnsize); if(tmp == NULL) { if (error) *error = MINISSDPC_MEMORY_ERROR; goto free_url_and_st_and_return; } tmp->pNext = devlist; tmp->descURL = tmp->buffer; tmp->st = tmp->buffer + 1 + urlsize; memcpy(tmp->buffer, url, urlsize); tmp->buffer[urlsize] = '\0'; memcpy(tmp->st, st, stsize); tmp->buffer[urlsize+1+stsize] = '\0'; free(url); free(st); url = NULL; st = NULL; tmp->usn = tmp->buffer + 1 + urlsize + 1 + stsize; READ_COPY_BUFFER(tmp->usn, usnsize); if(n<=0) { if (error) *error = MINISSDPC_INVALID_SERVER_REPLY; goto free_tmp_and_return; } tmp->buffer[urlsize+1+stsize+1+usnsize] = '\0'; tmp->scope_id = 0; /* default value. scope_id is not available with MiniSSDPd */ devlist = tmp; } if (error) *error = MINISSDPC_SUCCESS; return devlist; free_url_and_st_and_return: free(st); free_url_and_return: free(url); return devlist; free_tmp_and_return: free(tmp); return devlist; } #endif /* !(defined(_WIN32) || defined(__amigaos__) || defined(__amigaos4__)) */ /* parseMSEARCHReply() * the last 4 arguments are filled during the parsing : * - location/locationsize : "location:" field of the SSDP reply packet * - st/stsize : "st:" field of the SSDP reply packet. * - usn/usnsize : "usn:" filed of the SSDP reply packet * The strings are NOT null terminated */ static void parseMSEARCHReply(const char * reply, int size, const char * * location, int * locationsize, const char * * st, int * stsize, const char * * usn, int * usnsize) { int a, b, i; i = 0; a = i; /* start of the line */ b = 0; /* end of the "header" (position of the colon) */ while(isin6_family = AF_INET6; if(localport > 0 && localport < 65536) p->sin6_port = htons((unsigned short)localport); p->sin6_addr = in6addr_any; /* in6addr_any is not available with MinGW32 3.4.2 */ } else { struct sockaddr_in * p = (struct sockaddr_in *)&sockudp_r; p->sin_family = AF_INET; if(localport > 0 && localport < 65536) p->sin_port = htons((unsigned short)localport); p->sin_addr.s_addr = INADDR_ANY; } #ifdef _WIN32 /* This code could help us to use the right Network interface for * SSDP multicast traffic */ /* Get IP associated with the index given in the ip_forward struct * in order to give this ip to setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_IF) */ if(!ipv6) { DWORD ifbestidx; SOCKADDR_IN destAddr; memset(&destAddr, 0, sizeof(destAddr)); destAddr.sin_family = AF_INET; destAddr.sin_addr.s_addr = inet_addr("223.255.255.255"); destAddr.sin_port = 0; if (GetBestInterfaceEx((struct sockaddr *)&destAddr, &ifbestidx) == NO_ERROR) { DWORD dwRetVal = NO_ERROR; PIP_ADAPTER_ADDRESSES pAddresses = NULL; ULONG outBufLen = 15360; int Iterations; PIP_ADAPTER_ADDRESSES pCurrAddresses = NULL; PIP_ADAPTER_UNICAST_ADDRESS pUnicast = NULL; for (Iterations = 0; Iterations < 3; Iterations++) { pAddresses = (IP_ADAPTER_ADDRESSES *) HeapAlloc(GetProcessHeap(), 0, outBufLen); if (pAddresses == NULL) { break; } dwRetVal = GetAdaptersAddresses(AF_INET, GAA_FLAG_INCLUDE_PREFIX, NULL, pAddresses, &outBufLen); if (dwRetVal != ERROR_BUFFER_OVERFLOW) { break; } HeapFree(GetProcessHeap(), 0, pAddresses); pAddresses = NULL; } if (dwRetVal == NO_ERROR) { pCurrAddresses = pAddresses; while (pCurrAddresses) { #ifdef DEBUG int i; PIP_ADAPTER_MULTICAST_ADDRESS pMulticast = NULL; PIP_ADAPTER_ANYCAST_ADDRESS pAnycast = NULL; printf("\tIfIndex (IPv4 interface): %u\n", pCurrAddresses->IfIndex); printf("\tAdapter name: %s\n", pCurrAddresses->AdapterName); pUnicast = pCurrAddresses->FirstUnicastAddress; if (pUnicast != NULL) { for (i = 0; pUnicast != NULL; i++) { printf("\tIP Address[%d]: \t%s\n", i, inet_ntoa(((PSOCKADDR_IN)pUnicast->Address.lpSockaddr)->sin_addr) ); pUnicast = pUnicast->Next; } printf("\tNumber of Unicast Addresses: %d\n", i); } pAnycast = pCurrAddresses->FirstAnycastAddress; if (pAnycast) { for (i = 0; pAnycast != NULL; i++) { printf("\tAnycast Address[%d]: \t%s\n", i, inet_ntoa(((PSOCKADDR_IN)pAnycast->Address.lpSockaddr)->sin_addr) ); pAnycast = pAnycast->Next; } printf("\tNumber of Anycast Addresses: %d\n", i); } pMulticast = pCurrAddresses->FirstMulticastAddress; if (pMulticast) { for (i = 0; pMulticast != NULL; i++) { printf("\tMulticast Address[%d]: \t%s\n", i, inet_ntoa(((PSOCKADDR_IN)pMulticast->Address.lpSockaddr)->sin_addr) ); pMulticast = pMulticast->Next; } } printf("\n"); #endif pUnicast = pCurrAddresses->FirstUnicastAddress; if (pCurrAddresses->IfIndex == ifbestidx && pUnicast != NULL) { SOCKADDR_IN *ipv4 = (SOCKADDR_IN *)(pUnicast->Address.lpSockaddr); /* Set the address of this interface to be used */ struct in_addr mc_if; memset(&mc_if, 0, sizeof(mc_if)); mc_if.s_addr = ipv4->sin_addr.s_addr; if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_IF, (const char *)&mc_if, sizeof(mc_if)) < 0) { PRINT_SOCKET_ERROR("setsockopt"); } ((struct sockaddr_in *)&sockudp_r)->sin_addr.s_addr = ipv4->sin_addr.s_addr; #ifndef DEBUG break; #endif } pCurrAddresses = pCurrAddresses->Next; } } if (pAddresses != NULL) { HeapFree(GetProcessHeap(), 0, pAddresses); pAddresses = NULL; } } } #endif /* _WIN32 */ #ifdef _WIN32 if (setsockopt(sudp, SOL_SOCKET, SO_REUSEADDR, (const char *)&opt, sizeof (opt)) < 0) #else if (setsockopt(sudp, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof (opt)) < 0) #endif { if(error) *error = MINISSDPC_SOCKET_ERROR; PRINT_SOCKET_ERROR("setsockopt(SO_REUSEADDR,...)"); goto error; } if(ipv6) { #ifdef _WIN32 DWORD mcastHops = ttl; if(setsockopt(sudp, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (const char *)&mcastHops, sizeof(mcastHops)) < 0) #else /* _WIN32 */ int mcastHops = ttl; if(setsockopt(sudp, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &mcastHops, sizeof(mcastHops)) < 0) #endif /* _WIN32 */ { PRINT_SOCKET_ERROR("setsockopt(IPV6_MULTICAST_HOPS,...)"); } } else { #ifdef _WIN32 if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_TTL, (const char *)&_ttl, sizeof(_ttl)) < 0) #else /* _WIN32 */ if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)) < 0) #endif /* _WIN32 */ { /* not a fatal error */ PRINT_SOCKET_ERROR("setsockopt(IP_MULTICAST_TTL,...)"); } } if(multicastif) { if(ipv6) { #if !defined(_WIN32) /* according to MSDN, if_nametoindex() is supported since * MS Windows Vista and MS Windows Server 2008. * http://msdn.microsoft.com/en-us/library/bb408409%28v=vs.85%29.aspx */ unsigned int ifindex = if_nametoindex(multicastif); /* eth0, etc. */ if(setsockopt(sudp, IPPROTO_IPV6, IPV6_MULTICAST_IF, &ifindex, sizeof(ifindex)) < 0) { PRINT_SOCKET_ERROR("setsockopt IPV6_MULTICAST_IF"); } #else #ifdef DEBUG printf("Setting of multicast interface not supported in IPv6 under Windows.\n"); #endif #endif } else { struct in_addr mc_if; #if defined(_WIN32) && (_WIN32_WINNT >= _WIN32_WINNT_VISTA) InetPtonA(AF_INET, multicastif, &mc_if); #else mc_if.s_addr = inet_addr(multicastif); /* ex: 192.168.x.x */ #endif if(mc_if.s_addr != INADDR_NONE) { ((struct sockaddr_in *)&sockudp_r)->sin_addr.s_addr = mc_if.s_addr; if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_IF, (const char *)&mc_if, sizeof(mc_if)) < 0) { PRINT_SOCKET_ERROR("setsockopt IP_MULTICAST_IF"); } } else { #ifdef HAS_IP_MREQN /* was not an ip address, try with an interface name */ struct ip_mreqn reqn; /* only defined with -D_BSD_SOURCE or -D_GNU_SOURCE */ memset(&reqn, 0, sizeof(struct ip_mreqn)); reqn.imr_ifindex = if_nametoindex(multicastif); if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_IF, (const char *)&reqn, sizeof(reqn)) < 0) { PRINT_SOCKET_ERROR("setsockopt IP_MULTICAST_IF"); } #elif !defined(_WIN32) struct ifreq ifr; int ifrlen = sizeof(ifr); strncpy(ifr.ifr_name, multicastif, IFNAMSIZ); ifr.ifr_name[IFNAMSIZ-1] = '\0'; if(ioctl(sudp, SIOCGIFADDR, &ifr, &ifrlen) < 0) { PRINT_SOCKET_ERROR("ioctl(...SIOCGIFADDR...)"); } mc_if.s_addr = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr; if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_IF, (const char *)&mc_if, sizeof(mc_if)) < 0) { PRINT_SOCKET_ERROR("setsockopt IP_MULTICAST_IF"); } #else /* _WIN32 */ #ifdef DEBUG printf("Setting of multicast interface not supported with interface name.\n"); #endif #endif /* #ifdef HAS_IP_MREQN / !defined(_WIN32) */ } } } /* Before sending the packed, we first "bind" in order to be able * to receive the response */ if (bind(sudp, (const struct sockaddr *)&sockudp_r, ipv6 ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in)) != 0) { if(error) *error = MINISSDPC_SOCKET_ERROR; PRINT_SOCKET_ERROR("bind"); closesocket(sudp); return NULL; } if(error) *error = MINISSDPC_SUCCESS; /* Calculating maximum response time in seconds */ mx = ((unsigned int)delay) / 1000u; if(mx == 0) { mx = 1; delay = 1000; } /* receiving SSDP response packet */ for(deviceIndex = 0; deviceTypes[deviceIndex]; deviceIndex++) { sentok = 0; /* sending the SSDP M-SEARCH packet */ n = snprintf(bufr, sizeof(bufr), MSearchMsgFmt, ipv6 ? (linklocal ? "[" UPNP_MCAST_LL_ADDR "]" : "[" UPNP_MCAST_SL_ADDR "]") : UPNP_MCAST_ADDR, deviceTypes[deviceIndex], mx); if ((unsigned int)n >= sizeof(bufr)) { if(error) *error = MINISSDPC_MEMORY_ERROR; goto error; } #ifdef DEBUG /*printf("Sending %s", bufr);*/ printf("Sending M-SEARCH request to %s with ST: %s\n", ipv6 ? (linklocal ? "[" UPNP_MCAST_LL_ADDR "]" : "[" UPNP_MCAST_SL_ADDR "]") : UPNP_MCAST_ADDR, deviceTypes[deviceIndex]); #endif #ifdef NO_GETADDRINFO /* the following code is not using getaddrinfo */ /* emission */ memset(&sockudp_w, 0, sizeof(struct sockaddr_storage)); if(ipv6) { struct sockaddr_in6 * p = (struct sockaddr_in6 *)&sockudp_w; p->sin6_family = AF_INET6; p->sin6_port = htons(SSDP_PORT); inet_pton(AF_INET6, linklocal ? UPNP_MCAST_LL_ADDR : UPNP_MCAST_SL_ADDR, &(p->sin6_addr)); } else { struct sockaddr_in * p = (struct sockaddr_in *)&sockudp_w; p->sin_family = AF_INET; p->sin_port = htons(SSDP_PORT); p->sin_addr.s_addr = inet_addr(UPNP_MCAST_ADDR); } n = sendto(sudp, bufr, n, 0, &sockudp_w, ipv6 ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in)); if (n < 0) { if(error) *error = MINISSDPC_SOCKET_ERROR; PRINT_SOCKET_ERROR("sendto"); } else { sentok = 1; } #else /* #ifdef NO_GETADDRINFO */ memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC; /* AF_INET6 or AF_INET */ hints.ai_socktype = SOCK_DGRAM; /*hints.ai_flags = */ if ((rv = getaddrinfo(ipv6 ? (linklocal ? UPNP_MCAST_LL_ADDR : UPNP_MCAST_SL_ADDR) : UPNP_MCAST_ADDR, XSTR(SSDP_PORT), &hints, &servinfo)) != 0) { if(error) *error = MINISSDPC_SOCKET_ERROR; #ifdef _WIN32 fprintf(stderr, "getaddrinfo() failed: %d\n", rv); #else fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv)); #endif break; } else { struct addrinfo *p; for(p = servinfo; p; p = p->ai_next) { n = sendto(sudp, bufr, n, 0, p->ai_addr, MSC_CAST_INT p->ai_addrlen); if (n < 0) { #ifdef DEBUG char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV]; if (getnameinfo(p->ai_addr, (socklen_t)p->ai_addrlen, hbuf, sizeof(hbuf), sbuf, sizeof(sbuf), NI_NUMERICHOST | NI_NUMERICSERV) == 0) { fprintf(stderr, "host:%s port:%s\n", hbuf, sbuf); } #endif PRINT_SOCKET_ERROR("sendto"); continue; } else { sentok = 1; } } freeaddrinfo(servinfo); } if(!sentok) { if(error) *error = MINISSDPC_SOCKET_ERROR; } #endif /* #ifdef NO_GETADDRINFO */ /* Waiting for SSDP REPLY packet to M-SEARCH * if searchalltypes is set, enter the loop only * when the last deviceType is reached */ if((sentok && !searchalltypes) || !deviceTypes[deviceIndex + 1]) do { n = receivedata(sudp, bufr, sizeof(bufr), delay, &scope_id); if (n < 0) { /* error */ if(error) *error = MINISSDPC_SOCKET_ERROR; goto error; } else if (n == 0) { /* no data or Time Out */ #ifdef DEBUG printf("NODATA or TIMEOUT\n"); #endif /* DEBUG */ if (devlist && !searchalltypes) { /* found some devices, stop now*/ if(error) *error = MINISSDPC_SUCCESS; goto error; } } else { const char * descURL=NULL; int urlsize=0; const char * st=NULL; int stsize=0; const char * usn=NULL; int usnsize=0; parseMSEARCHReply(bufr, n, &descURL, &urlsize, &st, &stsize, &usn, &usnsize); if(st&&descURL) { #ifdef DEBUG printf("M-SEARCH Reply:\n ST: %.*s\n USN: %.*s\n Location: %.*s\n", stsize, st, usnsize, (usn?usn:""), urlsize, descURL); #endif /* DEBUG */ for(tmp=devlist; tmp; tmp = tmp->pNext) { if(strncmp(tmp->descURL, descURL, urlsize) == 0 && tmp->descURL[urlsize] == '\0' && strncmp(tmp->st, st, stsize) == 0 && tmp->st[stsize] == '\0' && (usnsize == 0 || strncmp(tmp->usn, usn, usnsize) == 0) && tmp->usn[usnsize] == '\0') break; } /* at the exit of the loop above, tmp is null if * no duplicate device was found */ if(tmp) continue; tmp = (struct UPNPDev *)malloc(sizeof(struct UPNPDev)+urlsize+stsize+usnsize); if(!tmp) { /* memory allocation error */ if(error) *error = MINISSDPC_MEMORY_ERROR; goto error; } tmp->pNext = devlist; tmp->descURL = tmp->buffer; tmp->st = tmp->buffer + 1 + urlsize; tmp->usn = tmp->st + 1 + stsize; memcpy(tmp->buffer, descURL, urlsize); tmp->buffer[urlsize] = '\0'; memcpy(tmp->st, st, stsize); tmp->buffer[urlsize+1+stsize] = '\0'; if(usn != NULL) memcpy(tmp->usn, usn, usnsize); tmp->buffer[urlsize+1+stsize+1+usnsize] = '\0'; tmp->scope_id = scope_id; devlist = tmp; } } } while(n > 0); if(ipv6) { /* switch linklocal flag */ if(linklocal) { linklocal = 0; --deviceIndex; } else { linklocal = 1; } } } error: closesocket(sudp); return devlist; } opengnb-ver1.6.0.a/libs/miniupnpc/minissdpc.h000066400000000000000000000031401500454252100211730ustar00rootroot00000000000000/* $Id: minissdpc.h,v 1.8 2019/02/10 12:29:23 nanard Exp $ */ /* Project: miniupnp * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ * Author: Thomas Bernard * Copyright (c) 2005-2015 Thomas Bernard * This software is subjects to the conditions detailed * in the LICENCE file provided within this distribution */ #ifndef MINISSDPC_H_INCLUDED #define MINISSDPC_H_INCLUDED #include "miniupnpc_declspec.h" #include "upnpdev.h" /* error codes : */ #define MINISSDPC_SUCCESS (0) #define MINISSDPC_UNKNOWN_ERROR (-1) #define MINISSDPC_SOCKET_ERROR (-101) #define MINISSDPC_MEMORY_ERROR (-102) #define MINISSDPC_INVALID_INPUT (-103) #define MINISSDPC_INVALID_SERVER_REPLY (-104) #ifdef __cplusplus extern "C" { #endif #if !(defined(_WIN32) || defined(__amigaos__) || defined(__amigaos4__)) MINIUPNP_LIBSPEC struct UPNPDev * getDevicesFromMiniSSDPD(const char * devtype, const char * socketpath, int * error); MINIUPNP_LIBSPEC int connectToMiniSSDPD(const char * socketpath); MINIUPNP_LIBSPEC int disconnectFromMiniSSDPD(int s); MINIUPNP_LIBSPEC int requestDevicesFromMiniSSDPD(int s, const char * devtype); MINIUPNP_LIBSPEC struct UPNPDev * receiveDevicesFromMiniSSDPD(int s, int * error); #endif /* !(defined(_WIN32) || defined(__amigaos__) || defined(__amigaos4__)) */ MINIUPNP_LIBSPEC struct UPNPDev * ssdpDiscoverDevices(const char * const deviceTypes[], int delay, const char * multicastif, int localport, int ipv6, unsigned char ttl, int * error, int searchalltypes); #ifdef __cplusplus } #endif #endif opengnb-ver1.6.0.a/libs/miniupnpc/miniupnpc.c000066400000000000000000000505061500454252100212070ustar00rootroot00000000000000/* $Id: miniupnpc.c,v 1.155 2019/12/23 23:14:44 nanard Exp $ */ /* vim: tabstop=4 shiftwidth=4 noexpandtab * Project : miniupnp * Web : http://miniupnp.free.fr/ * Author : Thomas BERNARD * copyright (c) 2005-2019 Thomas Bernard * This software is subjet to the conditions detailed in the * provided LICENSE file. */ #include #include #include #ifdef _WIN32 /* Win32 Specific includes and defines */ #include #include #include #include #define snprintf _snprintf #define strdup _strdup #ifndef strncasecmp #if defined(_MSC_VER) && (_MSC_VER >= 1400) #define strncasecmp _memicmp #else /* defined(_MSC_VER) && (_MSC_VER >= 1400) */ #define strncasecmp memicmp #endif /* defined(_MSC_VER) && (_MSC_VER >= 1400) */ #endif /* #ifndef strncasecmp */ #define MAXHOSTNAMELEN 64 #else /* #ifdef _WIN32 */ /* Standard POSIX includes */ #include #if defined(__amigaos__) && !defined(__amigaos4__) /* Amiga OS 3 specific stuff */ #define socklen_t int #else #include #endif #include #include #include #include #include #include #include #if !defined(__amigaos__) && !defined(__amigaos4__) #include #endif #include #include #define closesocket close #endif /* #else _WIN32 */ #ifdef __GNU__ #define MAXHOSTNAMELEN 64 #endif #include "miniupnpc.h" #include "minissdpc.h" #include "miniwget.h" #include "miniwget_private.h" #include "minisoap.h" #include "minixml.h" #include "upnpcommands.h" #include "connecthostport.h" /* compare the beginning of a string with a constant string */ #define COMPARE(str, cstr) (0==strncmp(str, cstr, sizeof(cstr) - 1)) #ifndef MAXHOSTNAMELEN #define MAXHOSTNAMELEN 64 #endif #define SOAPPREFIX "s" #define SERVICEPREFIX "u" #define SERVICEPREFIX2 'u' /* check if an ip address is a private (LAN) address * see https://tools.ietf.org/html/rfc1918 */ static int is_rfc1918addr(const char * addr) { /* 192.168.0.0 - 192.168.255.255 (192.168/16 prefix) */ if(COMPARE(addr, "192.168.")) return 1; /* 10.0.0.0 - 10.255.255.255 (10/8 prefix) */ if(COMPARE(addr, "10.")) return 1; /* 172.16.0.0 - 172.31.255.255 (172.16/12 prefix) */ if(COMPARE(addr, "172.")) { if((atoi(addr + 4) | 0x0f) == 0x1f) return 1; } return 0; } /* root description parsing */ MINIUPNP_LIBSPEC void parserootdesc(const char * buffer, int bufsize, struct IGDdatas * data) { struct xmlparser parser; /* xmlparser object */ parser.xmlstart = buffer; parser.xmlsize = bufsize; parser.data = data; parser.starteltfunc = IGDstartelt; parser.endeltfunc = IGDendelt; parser.datafunc = IGDdata; parser.attfunc = 0; parsexml(&parser); #ifdef DEBUG printIGD(data); #endif } /* simpleUPnPcommand2 : * not so simple ! * return values : * pointer - OK * NULL - error */ static char * simpleUPnPcommand2(SOCKET s, const char * url, const char * service, const char * action, struct UPNParg * args, int * bufsize, const char * httpversion) { char hostname[MAXHOSTNAMELEN+1]; unsigned short port = 0; char * path; char soapact[128]; char soapbody[2048]; int soapbodylen; char * buf; int n; int status_code; *bufsize = 0; snprintf(soapact, sizeof(soapact), "%s#%s", service, action); if(args==NULL) { soapbodylen = snprintf(soapbody, sizeof(soapbody), "\r\n" "<" SOAPPREFIX ":Envelope " "xmlns:" SOAPPREFIX "=\"http://schemas.xmlsoap.org/soap/envelope/\" " SOAPPREFIX ":encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">" "<" SOAPPREFIX ":Body>" "<" SERVICEPREFIX ":%s xmlns:" SERVICEPREFIX "=\"%s\">" "" "" "\r\n", action, service, action); if ((unsigned int)soapbodylen >= sizeof(soapbody)) return NULL; } else { char * p; const char * pe, * pv; const char * const pend = soapbody + sizeof(soapbody); soapbodylen = snprintf(soapbody, sizeof(soapbody), "\r\n" "<" SOAPPREFIX ":Envelope " "xmlns:" SOAPPREFIX "=\"http://schemas.xmlsoap.org/soap/envelope/\" " SOAPPREFIX ":encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">" "<" SOAPPREFIX ":Body>" "<" SERVICEPREFIX ":%s xmlns:" SERVICEPREFIX "=\"%s\">", action, service); if ((unsigned int)soapbodylen >= sizeof(soapbody)) return NULL; p = soapbody + soapbodylen; while(args->elt) { if(p >= pend) /* check for space to write next byte */ return NULL; *(p++) = '<'; pe = args->elt; while(p < pend && *pe) *(p++) = *(pe++); if(p >= pend) /* check for space to write next byte */ return NULL; *(p++) = '>'; if((pv = args->val)) { while(p < pend && *pv) *(p++) = *(pv++); } if((p+2) > pend) /* check for space to write next 2 bytes */ return NULL; *(p++) = '<'; *(p++) = '/'; pe = args->elt; while(p < pend && *pe) *(p++) = *(pe++); if(p >= pend) /* check for space to write next byte */ return NULL; *(p++) = '>'; args++; } if((p+4) > pend) /* check for space to write next 4 bytes */ return NULL; *(p++) = '<'; *(p++) = '/'; *(p++) = SERVICEPREFIX2; *(p++) = ':'; pe = action; while(p < pend && *pe) *(p++) = *(pe++); strncpy(p, ">\r\n", pend - p); if(soapbody[sizeof(soapbody)-1]) /* strncpy pads buffer with 0s, so if it doesn't end in 0, could not fit full string */ return NULL; } if(!parseURL(url, hostname, &port, &path, NULL)) return NULL; if(ISINVALID(s)) { s = connecthostport(hostname, port, 0); if(ISINVALID(s)) { /* failed to connect */ return NULL; } } n = soapPostSubmit(s, path, hostname, port, soapact, soapbody, httpversion); if(n<=0) { #ifdef DEBUG printf("Error sending SOAP request\n"); #endif closesocket(s); return NULL; } buf = getHTTPResponse(s, bufsize, &status_code); #ifdef DEBUG if(*bufsize > 0 && buf) { printf("HTTP %d SOAP Response :\n%.*s\n", status_code, *bufsize, buf); } else { printf("HTTP %d, empty SOAP response. size=%d\n", status_code, *bufsize); } #endif closesocket(s); return buf; } /* simpleUPnPcommand : * not so simple ! * return values : * pointer - OK * NULL - error */ char * simpleUPnPcommand(int s, const char * url, const char * service, const char * action, struct UPNParg * args, int * bufsize) { char * buf; #if 1 buf = simpleUPnPcommand2((SOCKET)s, url, service, action, args, bufsize, "1.1"); #else buf = simpleUPnPcommand2((SOCKET)s, url, service, action, args, bufsize, "1.0"); if (!buf || *bufsize == 0) { #if DEBUG printf("Error or no result from SOAP request; retrying with HTTP/1.1\n"); #endif buf = simpleUPnPcommand2((SOCKET)s, url, service, action, args, bufsize, "1.1"); } #endif return buf; } /* upnpDiscoverDevices() : * return a chained list of all devices found or NULL if * no devices was found. * It is up to the caller to free the chained list * delay is in millisecond (poll). * UDA v1.1 says : * The TTL for the IP packet SHOULD default to 2 and * SHOULD be configurable. */ MINIUPNP_LIBSPEC struct UPNPDev * upnpDiscoverDevices(const char * const deviceTypes[], int delay, const char * multicastif, const char * minissdpdsock, int localport, int ipv6, unsigned char ttl, int * error, int searchalltypes) { struct UPNPDev * tmp; struct UPNPDev * devlist = 0; #if !defined(_WIN32) && !defined(__amigaos__) && !defined(__amigaos4__) int deviceIndex; #endif /* !defined(_WIN32) && !defined(__amigaos__) && !defined(__amigaos4__) */ if(error) *error = UPNPDISCOVER_UNKNOWN_ERROR; #if !defined(_WIN32) && !defined(__amigaos__) && !defined(__amigaos4__) /* first try to get infos from minissdpd ! */ if(!minissdpdsock) minissdpdsock = "/var/run/minissdpd.sock"; if(minissdpdsock[0] != '\0') { for(deviceIndex = 0; deviceTypes[deviceIndex]; deviceIndex++) { struct UPNPDev * minissdpd_devlist; int only_rootdevice = 1; minissdpd_devlist = getDevicesFromMiniSSDPD(deviceTypes[deviceIndex], minissdpdsock, 0); if(minissdpd_devlist) { #ifdef DEBUG printf("returned by MiniSSDPD: %s\t%s\n", minissdpd_devlist->st, minissdpd_devlist->descURL); #endif /* DEBUG */ if(!strstr(minissdpd_devlist->st, "rootdevice")) only_rootdevice = 0; for(tmp = minissdpd_devlist; tmp->pNext != NULL; tmp = tmp->pNext) { #ifdef DEBUG printf("returned by MiniSSDPD: %s\t%s\n", tmp->pNext->st, tmp->pNext->descURL); #endif /* DEBUG */ if(!strstr(tmp->st, "rootdevice")) only_rootdevice = 0; } tmp->pNext = devlist; devlist = minissdpd_devlist; if(!searchalltypes && !only_rootdevice) break; } } } for(tmp = devlist; tmp != NULL; tmp = tmp->pNext) { /* We return what we have found if it was not only a rootdevice */ if(!strstr(tmp->st, "rootdevice")) { if(error) *error = UPNPDISCOVER_SUCCESS; return devlist; } } #endif /* !defined(_WIN32) && !defined(__amigaos__) && !defined(__amigaos4__) */ /* direct discovery if minissdpd responses are not sufficient */ { struct UPNPDev * discovered_devlist; discovered_devlist = ssdpDiscoverDevices(deviceTypes, delay, multicastif, localport, ipv6, ttl, error, searchalltypes); if(devlist == NULL) devlist = discovered_devlist; else { for(tmp = devlist; tmp->pNext != NULL; tmp = tmp->pNext); tmp->pNext = discovered_devlist; } } return devlist; } /* upnpDiscover() Discover IGD device */ MINIUPNP_LIBSPEC struct UPNPDev * upnpDiscover(int delay, const char * multicastif, const char * minissdpdsock, int localport, int ipv6, unsigned char ttl, int * error) { static const char * const deviceList[] = { #if 0 "urn:schemas-upnp-org:device:InternetGatewayDevice:2", "urn:schemas-upnp-org:service:WANIPConnection:2", #endif "urn:schemas-upnp-org:device:InternetGatewayDevice:1", "urn:schemas-upnp-org:service:WANIPConnection:1", "urn:schemas-upnp-org:service:WANPPPConnection:1", "upnp:rootdevice", /*"ssdp:all",*/ 0 }; return upnpDiscoverDevices(deviceList, delay, multicastif, minissdpdsock, localport, ipv6, ttl, error, 0); } /* upnpDiscoverAll() Discover all UPnP devices */ MINIUPNP_LIBSPEC struct UPNPDev * upnpDiscoverAll(int delay, const char * multicastif, const char * minissdpdsock, int localport, int ipv6, unsigned char ttl, int * error) { static const char * const deviceList[] = { /*"upnp:rootdevice",*/ "ssdp:all", 0 }; return upnpDiscoverDevices(deviceList, delay, multicastif, minissdpdsock, localport, ipv6, ttl, error, 0); } /* upnpDiscoverDevice() Discover a specific device */ MINIUPNP_LIBSPEC struct UPNPDev * upnpDiscoverDevice(const char * device, int delay, const char * multicastif, const char * minissdpdsock, int localport, int ipv6, unsigned char ttl, int * error) { const char * const deviceList[] = { device, 0 }; return upnpDiscoverDevices(deviceList, delay, multicastif, minissdpdsock, localport, ipv6, ttl, error, 0); } static char * build_absolute_url(const char * baseurl, const char * descURL, const char * url, unsigned int scope_id) { size_t l, n; char * s; const char * base; char * p; #if defined(IF_NAMESIZE) && !defined(_WIN32) char ifname[IF_NAMESIZE]; #else /* defined(IF_NAMESIZE) && !defined(_WIN32) */ char scope_str[8]; #endif /* defined(IF_NAMESIZE) && !defined(_WIN32) */ if( (url[0] == 'h') &&(url[1] == 't') &&(url[2] == 't') &&(url[3] == 'p') &&(url[4] == ':') &&(url[5] == '/') &&(url[6] == '/')) return strdup(url); base = (baseurl[0] == '\0') ? descURL : baseurl; n = strlen(base); if(n > 7) { p = strchr(base + 7, '/'); if(p) n = p - base; } l = n + strlen(url) + 1; if(url[0] != '/') l++; if(scope_id != 0) { #if defined(IF_NAMESIZE) && !defined(_WIN32) if(if_indextoname(scope_id, ifname)) { l += 3 + strlen(ifname); /* 3 == strlen(%25) */ } #else /* defined(IF_NAMESIZE) && !defined(_WIN32) */ /* under windows, scope is numerical */ l += 3 + snprintf(scope_str, sizeof(scope_str), "%u", scope_id); #endif /* defined(IF_NAMESIZE) && !defined(_WIN32) */ } s = malloc(l); if(s == NULL) return NULL; memcpy(s, base, n); if(scope_id != 0) { s[n] = '\0'; if(n > 13 && 0 == memcmp(s, "http://[fe80:", 13)) { /* this is a linklocal IPv6 address */ p = strchr(s, ']'); if(p) { /* insert %25 into URL */ #if defined(IF_NAMESIZE) && !defined(_WIN32) memmove(p + 3 + strlen(ifname), p, strlen(p) + 1); memcpy(p, "%25", 3); memcpy(p + 3, ifname, strlen(ifname)); n += 3 + strlen(ifname); #else /* defined(IF_NAMESIZE) && !defined(_WIN32) */ memmove(p + 3 + strlen(scope_str), p, strlen(p) + 1); memcpy(p, "%25", 3); memcpy(p + 3, scope_str, strlen(scope_str)); n += 3 + strlen(scope_str); #endif /* defined(IF_NAMESIZE) && !defined(_WIN32) */ } } } if(url[0] != '/') s[n++] = '/'; memcpy(s + n, url, l - n); return s; } /* Prepare the Urls for usage... */ MINIUPNP_LIBSPEC void GetUPNPUrls(struct UPNPUrls * urls, struct IGDdatas * data, const char * descURL, unsigned int scope_id) { /* strdup descURL */ urls->rootdescURL = strdup(descURL); /* get description of WANIPConnection */ urls->ipcondescURL = build_absolute_url(data->urlbase, descURL, data->first.scpdurl, scope_id); urls->controlURL = build_absolute_url(data->urlbase, descURL, data->first.controlurl, scope_id); urls->controlURL_CIF = build_absolute_url(data->urlbase, descURL, data->CIF.controlurl, scope_id); urls->controlURL_6FC = build_absolute_url(data->urlbase, descURL, data->IPv6FC.controlurl, scope_id); #ifdef DEBUG printf("urls->ipcondescURL='%s'\n", urls->ipcondescURL); printf("urls->controlURL='%s'\n", urls->controlURL); printf("urls->controlURL_CIF='%s'\n", urls->controlURL_CIF); printf("urls->controlURL_6FC='%s'\n", urls->controlURL_6FC); #endif } MINIUPNP_LIBSPEC void FreeUPNPUrls(struct UPNPUrls * urls) { if(!urls) return; free(urls->controlURL); urls->controlURL = 0; free(urls->ipcondescURL); urls->ipcondescURL = 0; free(urls->controlURL_CIF); urls->controlURL_CIF = 0; free(urls->controlURL_6FC); urls->controlURL_6FC = 0; free(urls->rootdescURL); urls->rootdescURL = 0; } int UPNPIGD_IsConnected(struct UPNPUrls * urls, struct IGDdatas * data) { char status[64]; unsigned int uptime; status[0] = '\0'; UPNP_GetStatusInfo(urls->controlURL, data->first.servicetype, status, &uptime, NULL); if(0 == strcmp("Connected", status)) return 1; else if(0 == strcmp("Up", status)) /* Also accept "Up" */ return 1; else return 0; } /* UPNP_GetValidIGD() : * return values : * -1 = Internal error * 0 = NO IGD found * 1 = A valid connected IGD has been found * 2 = A valid IGD has been found but it reported as * not connected * 3 = an UPnP device has been found but was not recognized as an IGD * * In any positive non zero return case, the urls and data structures * passed as parameters are set. Don't forget to call FreeUPNPUrls(urls) to * free allocated memory. */ MINIUPNP_LIBSPEC int UPNP_GetValidIGD(struct UPNPDev * devlist, struct UPNPUrls * urls, struct IGDdatas * data, char * lanaddr, int lanaddrlen) { struct xml_desc { char lanaddr[40]; char * xml; int size; int is_igd; } * desc = NULL; struct UPNPDev * dev; int ndev = 0; int i; int state = -1; /* state 1 : IGD connected. State 2 : IGD. State 3 : anything */ char extIpAddr[16]; int status_code = -1; if(!devlist) { #ifdef DEBUG printf("Empty devlist\n"); #endif return 0; } /* counting total number of devices in the list */ for(dev = devlist; dev; dev = dev->pNext) ndev++; /* ndev is always > 0 */ desc = calloc(ndev, sizeof(struct xml_desc)); if(!desc) return -1; /* memory allocation error */ /* Step 1 : downloading descriptions and testing type */ for(dev = devlist, i = 0; dev; dev = dev->pNext, i++) { /* we should choose an internet gateway device. * with st == urn:schemas-upnp-org:device:InternetGatewayDevice:1 */ desc[i].xml = miniwget_getaddr(dev->descURL, &(desc[i].size), desc[i].lanaddr, sizeof(desc[i].lanaddr), dev->scope_id, &status_code); #ifdef DEBUG if(!desc[i].xml) { printf("error getting XML description %s\n", dev->descURL); } #endif if(desc[i].xml) { memset(data, 0, sizeof(struct IGDdatas)); memset(urls, 0, sizeof(struct UPNPUrls)); parserootdesc(desc[i].xml, desc[i].size, data); if(COMPARE(data->CIF.servicetype, "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:")) { desc[i].is_igd = 1; } } } /* iterate the list to find a device depending on state */ for(state = 1; state <= 3; state++) { for(dev = devlist, i = 0; dev; dev = dev->pNext, i++) { if(desc[i].xml) { memset(data, 0, sizeof(struct IGDdatas)); memset(urls, 0, sizeof(struct UPNPUrls)); parserootdesc(desc[i].xml, desc[i].size, data); if(desc[i].is_igd || state >= 3 ) { int is_connected; GetUPNPUrls(urls, data, dev->descURL, dev->scope_id); /* in state 2 and 3 we don't test if device is connected ! */ if(state >= 2) goto free_and_return; is_connected = UPNPIGD_IsConnected(urls, data); #ifdef DEBUG printf("UPNPIGD_IsConnected(%s) = %d\n", urls->controlURL, is_connected); #endif /* checks that status is connected AND there is a external IP address assigned */ if(is_connected && (UPNP_GetExternalIPAddress(urls->controlURL, data->first.servicetype, extIpAddr) == 0)) { if(!is_rfc1918addr(extIpAddr) && (extIpAddr[0] != '\0') && (0 != strcmp(extIpAddr, "0.0.0.0"))) goto free_and_return; } FreeUPNPUrls(urls); if(data->second.servicetype[0] != '\0') { #ifdef DEBUG printf("We tried %s, now we try %s !\n", data->first.servicetype, data->second.servicetype); #endif /* swaping WANPPPConnection and WANIPConnection ! */ memcpy(&data->tmp, &data->first, sizeof(struct IGDdatas_service)); memcpy(&data->first, &data->second, sizeof(struct IGDdatas_service)); memcpy(&data->second, &data->tmp, sizeof(struct IGDdatas_service)); GetUPNPUrls(urls, data, dev->descURL, dev->scope_id); is_connected = UPNPIGD_IsConnected(urls, data); #ifdef DEBUG printf("UPNPIGD_IsConnected(%s) = %d\n", urls->controlURL, is_connected); #endif if(is_connected && (UPNP_GetExternalIPAddress(urls->controlURL, data->first.servicetype, extIpAddr) == 0)) { if(!is_rfc1918addr(extIpAddr) && (extIpAddr[0] != '\0') && (0 != strcmp(extIpAddr, "0.0.0.0"))) goto free_and_return; } FreeUPNPUrls(urls); } } memset(data, 0, sizeof(struct IGDdatas)); } } } state = 0; free_and_return: if (lanaddr != NULL && state >= 1 && state <= 3 && i < ndev) strncpy(lanaddr, desc[i].lanaddr, lanaddrlen); for(i = 0; i < ndev; i++) free(desc[i].xml); free(desc); return state; } /* UPNP_GetIGDFromUrl() * Used when skipping the discovery process. * return value : * 0 - Not ok * 1 - OK */ int UPNP_GetIGDFromUrl(const char * rootdescurl, struct UPNPUrls * urls, struct IGDdatas * data, char * lanaddr, int lanaddrlen) { char * descXML; int descXMLsize = 0; descXML = miniwget_getaddr(rootdescurl, &descXMLsize, lanaddr, lanaddrlen, 0, NULL); if(descXML) { memset(data, 0, sizeof(struct IGDdatas)); memset(urls, 0, sizeof(struct UPNPUrls)); parserootdesc(descXML, descXMLsize, data); free(descXML); GetUPNPUrls(urls, data, rootdescurl, 0); return 1; } else { return 0; } } opengnb-ver1.6.0.a/libs/miniupnpc/miniupnpc.h000066400000000000000000000117761500454252100212220ustar00rootroot00000000000000/* $Id: miniupnpc.h,v 1.53 2018/05/07 11:05:16 nanard Exp $ */ /* vim: tabstop=4 shiftwidth=4 noexpandtab * Project: miniupnp * http://miniupnp.free.fr/ * Author: Thomas Bernard * Copyright (c) 2005-2018 Thomas Bernard * This software is subjects to the conditions detailed * in the LICENCE file provided within this distribution */ #ifndef MINIUPNPC_H_INCLUDED #define MINIUPNPC_H_INCLUDED #include "miniupnpc_declspec.h" #include "igd_desc_parse.h" #include "upnpdev.h" /* error codes : */ #define UPNPDISCOVER_SUCCESS (0) #define UPNPDISCOVER_UNKNOWN_ERROR (-1) #define UPNPDISCOVER_SOCKET_ERROR (-101) #define UPNPDISCOVER_MEMORY_ERROR (-102) /* versions : */ #define MINIUPNPC_VERSION "2.1.20191224" #define MINIUPNPC_API_VERSION 17 /* Source port: Using "1" as an alias for 1900 for backwards compatibility (presuming one would have used that for the "sameport" parameter) */ #define UPNP_LOCAL_PORT_ANY 0 #define UPNP_LOCAL_PORT_SAME 1 #ifdef __cplusplus extern "C" { #endif /* Structures definitions : */ struct UPNParg { const char * elt; const char * val; }; char * simpleUPnPcommand(int, const char *, const char *, const char *, struct UPNParg *, int *); /* upnpDiscover() * discover UPnP devices on the network. * The discovered devices are returned as a chained list. * It is up to the caller to free the list with freeUPNPDevlist(). * delay (in millisecond) is the maximum time for waiting any device * response. * If available, device list will be obtained from MiniSSDPd. * Default path for minissdpd socket will be used if minissdpdsock argument * is NULL. * If multicastif is not NULL, it will be used instead of the default * multicast interface for sending SSDP discover packets. * If localport is set to UPNP_LOCAL_PORT_SAME(1) SSDP packets will be sent * from the source port 1900 (same as destination port), if set to * UPNP_LOCAL_PORT_ANY(0) system assign a source port, any other value will * be attempted as the source port. * "searchalltypes" parameter is useful when searching several types, * if 0, the discovery will stop with the first type returning results. * TTL should default to 2. */ MINIUPNP_LIBSPEC struct UPNPDev * upnpDiscover(int delay, const char * multicastif, const char * minissdpdsock, int localport, int ipv6, unsigned char ttl, int * error); MINIUPNP_LIBSPEC struct UPNPDev * upnpDiscoverAll(int delay, const char * multicastif, const char * minissdpdsock, int localport, int ipv6, unsigned char ttl, int * error); MINIUPNP_LIBSPEC struct UPNPDev * upnpDiscoverDevice(const char * device, int delay, const char * multicastif, const char * minissdpdsock, int localport, int ipv6, unsigned char ttl, int * error); MINIUPNP_LIBSPEC struct UPNPDev * upnpDiscoverDevices(const char * const deviceTypes[], int delay, const char * multicastif, const char * minissdpdsock, int localport, int ipv6, unsigned char ttl, int * error, int searchalltypes); /* parserootdesc() : * parse root XML description of a UPnP device and fill the IGDdatas * structure. */ MINIUPNP_LIBSPEC void parserootdesc(const char *, int, struct IGDdatas *); /* structure used to get fast access to urls * controlURL: controlURL of the WANIPConnection * ipcondescURL: url of the description of the WANIPConnection * controlURL_CIF: controlURL of the WANCommonInterfaceConfig * controlURL_6FC: controlURL of the WANIPv6FirewallControl */ struct UPNPUrls { char * controlURL; char * ipcondescURL; char * controlURL_CIF; char * controlURL_6FC; char * rootdescURL; }; /* UPNP_GetValidIGD() : * return values : * 0 = NO IGD found * 1 = A valid connected IGD has been found * 2 = A valid IGD has been found but it reported as * not connected * 3 = an UPnP device has been found but was not recognized as an IGD * * In any non zero return case, the urls and data structures * passed as parameters are set. Donc forget to call FreeUPNPUrls(urls) to * free allocated memory. */ MINIUPNP_LIBSPEC int UPNP_GetValidIGD(struct UPNPDev * devlist, struct UPNPUrls * urls, struct IGDdatas * data, char * lanaddr, int lanaddrlen); /* UPNP_GetIGDFromUrl() * Used when skipping the discovery process. * When succeding, urls, data, and lanaddr arguments are set. * return value : * 0 - Not ok * 1 - OK */ MINIUPNP_LIBSPEC int UPNP_GetIGDFromUrl(const char * rootdescurl, struct UPNPUrls * urls, struct IGDdatas * data, char * lanaddr, int lanaddrlen); MINIUPNP_LIBSPEC void GetUPNPUrls(struct UPNPUrls *, struct IGDdatas *, const char *, unsigned int); MINIUPNP_LIBSPEC void FreeUPNPUrls(struct UPNPUrls *); /* return 0 or 1 */ MINIUPNP_LIBSPEC int UPNPIGD_IsConnected(struct UPNPUrls *, struct IGDdatas *); #ifdef __cplusplus } #endif #endif opengnb-ver1.6.0.a/libs/miniupnpc/miniupnpc_declspec.h000066400000000000000000000010601500454252100230450ustar00rootroot00000000000000#ifndef MINIUPNPC_DECLSPEC_H_INCLUDED #define MINIUPNPC_DECLSPEC_H_INCLUDED #if defined(_WIN32) && !defined(MINIUPNP_STATICLIB) /* for windows dll */ #ifdef MINIUPNP_EXPORTS #define MINIUPNP_LIBSPEC __declspec(dllexport) #else #define MINIUPNP_LIBSPEC __declspec(dllimport) #endif #else #if defined(__GNUC__) && __GNUC__ >= 4 /* fix dynlib for OS X 10.9.2 and Apple LLVM version 5.0 */ #define MINIUPNP_LIBSPEC __attribute__ ((visibility ("default"))) #else #define MINIUPNP_LIBSPEC #endif #endif #endif /* MINIUPNPC_DECLSPEC_H_INCLUDED */ opengnb-ver1.6.0.a/libs/miniupnpc/miniupnpc_socketdef.h000066400000000000000000000017701500454252100232420ustar00rootroot00000000000000/* $Id: miniupnpc_socketdef.h,v 1.3 2019/02/10 13:24:52 nanard Exp $ */ /* Miniupnp project : http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/ * Author : Thomas Bernard * Copyright (c) 2018 Thomas Bernard * This software is subject to the conditions detailed in the * LICENCE file provided within this distribution */ #ifndef MINIUPNPC_SOCKETDEF_H_INCLUDED #define MINIUPNPC_SOCKETDEF_H_INCLUDED #ifdef _MSC_VER #define ISINVALID(s) (INVALID_SOCKET==(s)) #else #ifndef SOCKET #define SOCKET int #endif #ifndef SSIZE_T #define SSIZE_T ssize_t #endif #ifndef INVALID_SOCKET #define INVALID_SOCKET (-1) #endif #ifndef ISINVALID #define ISINVALID(s) ((s)<0) #endif #endif #ifdef _MSC_VER #define MSC_CAST_INT (int) #else #define MSC_CAST_INT #endif /* definition of PRINT_SOCKET_ERROR */ #ifdef _WIN32 #define PRINT_SOCKET_ERROR(x) fprintf(stderr, "Socket error: %s, %d\n", x, WSAGetLastError()); #else #define PRINT_SOCKET_ERROR(x) perror(x) #endif #endif /* MINIUPNPC_SOCKETDEF_H_INCLUDED */ opengnb-ver1.6.0.a/libs/miniupnpc/miniupnpcstrings.h000066400000000000000000000012631500454252100226220ustar00rootroot00000000000000/* $Id: miniupnpcstrings.h.in,v 1.6 2014/11/04 22:31:55 nanard Exp $ */ /* Project: miniupnp * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ * Author: Thomas Bernard * Copyright (c) 2005-2014 Thomas Bernard * This software is subjects to the conditions detailed * in the LICENCE file provided within this distribution */ #ifndef MINIUPNPCSTRINGS_H_INCLUDED #define MINIUPNPCSTRINGS_H_INCLUDED #define OS_STRING "Ubuntu/18.04" #define MINIUPNPC_VERSION_STRING "2.1" #if 0 /* according to "UPnP Device Architecture 1.0" */ #define UPNP_VERSION_STRING "UPnP/1.0" #else /* according to "UPnP Device Architecture 1.1" */ #define UPNP_VERSION_STRING "UPnP/1.1" #endif #endif opengnb-ver1.6.0.a/libs/miniupnpc/miniupnpcstrings.h.in000066400000000000000000000012651500454252100232310ustar00rootroot00000000000000/* $Id: miniupnpcstrings.h.in,v 1.6 2014/11/04 22:31:55 nanard Exp $ */ /* Project: miniupnp * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ * Author: Thomas Bernard * Copyright (c) 2005-2014 Thomas Bernard * This software is subjects to the conditions detailed * in the LICENCE file provided within this distribution */ #ifndef MINIUPNPCSTRINGS_H_INCLUDED #define MINIUPNPCSTRINGS_H_INCLUDED #define OS_STRING "OS/version" #define MINIUPNPC_VERSION_STRING "version" #if 0 /* according to "UPnP Device Architecture 1.0" */ #define UPNP_VERSION_STRING "UPnP/1.0" #else /* according to "UPnP Device Architecture 1.1" */ #define UPNP_VERSION_STRING "UPnP/1.1" #endif #endif opengnb-ver1.6.0.a/libs/miniupnpc/miniupnpctypes.h000066400000000000000000000011421500454252100222710ustar00rootroot00000000000000/* $Id: miniupnpctypes.h,v 1.2 2012/09/27 15:42:10 nanard Exp $ */ /* Miniupnp project : http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org * Author : Thomas Bernard * Copyright (c) 2011 Thomas Bernard * This software is subject to the conditions detailed in the * LICENCE file provided within this distribution */ #ifndef MINIUPNPCTYPES_H_INCLUDED #define MINIUPNPCTYPES_H_INCLUDED #if (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L) #define UNSIGNED_INTEGER unsigned long long #define STRTOUI strtoull #else #define UNSIGNED_INTEGER unsigned int #define STRTOUI strtoul #endif #endif opengnb-ver1.6.0.a/libs/miniupnpc/miniwget.c000066400000000000000000000405661500454252100210350ustar00rootroot00000000000000/* $Id: miniwget.c,v 1.80 2019/02/10 13:22:05 nanard Exp $ */ /* Project : miniupnp * Website : http://miniupnp.free.fr/ * Author : Thomas Bernard * Copyright (c) 2005-2018 Thomas Bernard * This software is subject to the conditions detailed in the * LICENCE file provided in this distribution. */ #include #include #include #include #ifdef _WIN32 #include #include #include #define MAXHOSTNAMELEN 64 #define snprintf _snprintf #define socklen_t int #ifndef strncasecmp #if defined(_MSC_VER) && (_MSC_VER >= 1400) #define strncasecmp _memicmp #else /* defined(_MSC_VER) && (_MSC_VER >= 1400) */ #define strncasecmp memicmp #endif /* defined(_MSC_VER) && (_MSC_VER >= 1400) */ #endif /* #ifndef strncasecmp */ #else /* #ifdef _WIN32 */ #include #include #if defined(__amigaos__) && !defined(__amigaos4__) #define socklen_t int #else /* #if defined(__amigaos__) && !defined(__amigaos4__) */ #include #endif /* #else defined(__amigaos__) && !defined(__amigaos4__) */ #include #include #include #include #include #define closesocket close #include #endif /* #else _WIN32 */ #ifdef __GNU__ #define MAXHOSTNAMELEN 64 #endif /* __GNU__ */ #ifndef MIN #define MIN(x,y) (((x)<(y))?(x):(y)) #endif /* MIN */ #include "miniupnpcstrings.h" #include "miniwget.h" #include "connecthostport.h" #include "receivedata.h" #ifndef MAXHOSTNAMELEN #define MAXHOSTNAMELEN 64 #endif /* * Read a HTTP response from a socket. * Process Content-Length and Transfer-encoding headers. * return a pointer to the content buffer, which length is saved * to the length parameter. */ void * getHTTPResponse(SOCKET s, int * size, int * status_code) { char buf[2048]; int n; int endofheaders = 0; int chunked = 0; int content_length = -1; unsigned int chunksize = 0; unsigned int bytestocopy = 0; /* buffers : */ char * header_buf; unsigned int header_buf_len = 2048; unsigned int header_buf_used = 0; char * content_buf; unsigned int content_buf_len = 2048; unsigned int content_buf_used = 0; char chunksize_buf[32]; unsigned int chunksize_buf_index; #ifdef DEBUG char * reason_phrase = NULL; int reason_phrase_len = 0; #endif if(status_code) *status_code = -1; header_buf = malloc(header_buf_len); if(header_buf == NULL) { #ifdef DEBUG fprintf(stderr, "%s: Memory allocation error\n", "getHTTPResponse"); #endif /* DEBUG */ *size = -1; return NULL; } content_buf = malloc(content_buf_len); if(content_buf == NULL) { free(header_buf); #ifdef DEBUG fprintf(stderr, "%s: Memory allocation error\n", "getHTTPResponse"); #endif /* DEBUG */ *size = -1; return NULL; } chunksize_buf[0] = '\0'; chunksize_buf_index = 0; while((n = receivedata(s, buf, sizeof(buf), 5000, NULL)) > 0) { if(endofheaders == 0) { int i; int linestart=0; int colon=0; int valuestart=0; if(header_buf_used + n > header_buf_len) { char * tmp = realloc(header_buf, header_buf_used + n); if(tmp == NULL) { /* memory allocation error */ free(header_buf); free(content_buf); *size = -1; return NULL; } header_buf = tmp; header_buf_len = header_buf_used + n; } memcpy(header_buf + header_buf_used, buf, n); header_buf_used += n; /* search for CR LF CR LF (end of headers) * recognize also LF LF */ i = 0; while(i < ((int)header_buf_used-1) && (endofheaders == 0)) { if(header_buf[i] == '\r') { i++; if(header_buf[i] == '\n') { i++; if(i < (int)header_buf_used && header_buf[i] == '\r') { i++; if(i < (int)header_buf_used && header_buf[i] == '\n') { endofheaders = i+1; } } } } else if(header_buf[i] == '\n') { i++; if(header_buf[i] == '\n') { endofheaders = i+1; } } i++; } if(endofheaders == 0) continue; /* parse header lines */ for(i = 0; i < endofheaders - 1; i++) { if(linestart > 0 && colon <= linestart && header_buf[i]==':') { colon = i; while(i < (endofheaders-1) && (header_buf[i+1] == ' ' || header_buf[i+1] == '\t')) i++; valuestart = i + 1; } /* detecting end of line */ else if(header_buf[i]=='\r' || header_buf[i]=='\n') { if(linestart == 0 && status_code) { /* Status line * HTTP-Version SP Status-Code SP Reason-Phrase CRLF */ int sp; for(sp = 0; sp < i; sp++) if(header_buf[sp] == ' ') { if(*status_code < 0) *status_code = atoi(header_buf + sp + 1); else { #ifdef DEBUG reason_phrase = header_buf + sp + 1; reason_phrase_len = i - sp - 1; #endif break; } } #ifdef DEBUG printf("HTTP status code = %d, Reason phrase = %.*s\n", *status_code, reason_phrase_len, reason_phrase); #endif } else if(colon > linestart && valuestart > colon) { #ifdef DEBUG printf("header='%.*s', value='%.*s'\n", colon-linestart, header_buf+linestart, i-valuestart, header_buf+valuestart); #endif if(0==strncasecmp(header_buf+linestart, "content-length", colon-linestart)) { content_length = atoi(header_buf+valuestart); #ifdef DEBUG printf("Content-Length: %d\n", content_length); #endif } else if(0==strncasecmp(header_buf+linestart, "transfer-encoding", colon-linestart) && 0==strncasecmp(header_buf+valuestart, "chunked", 7)) { #ifdef DEBUG printf("chunked transfer-encoding!\n"); #endif chunked = 1; } } while((i < (int)header_buf_used) && (header_buf[i]=='\r' || header_buf[i] == '\n')) i++; linestart = i; colon = linestart; valuestart = 0; } } /* copy the remaining of the received data back to buf */ n = header_buf_used - endofheaders; memcpy(buf, header_buf + endofheaders, n); /* if(headers) */ } /* if we get there, endofheaders != 0. * In the other case, there was a continue above */ /* content */ if(chunked) { int i = 0; while(i < n) { if(chunksize == 0) { /* reading chunk size */ if(chunksize_buf_index == 0) { /* skipping any leading CR LF */ if(buf[i] == '\r') i++; if(i= '0' && chunksize_buf[j] <= '9') chunksize = (chunksize << 4) + (chunksize_buf[j] - '0'); else chunksize = (chunksize << 4) + ((chunksize_buf[j] | 32) - 'a' + 10); } chunksize_buf[0] = '\0'; chunksize_buf_index = 0; i++; } else { /* not finished to get chunksize */ continue; } #ifdef DEBUG printf("chunksize = %u (%x)\n", chunksize, chunksize); #endif if(chunksize == 0) { #ifdef DEBUG printf("end of HTTP content - %d %d\n", i, n); /*printf("'%.*s'\n", n-i, buf+i);*/ #endif goto end_of_stream; } } /* it is guaranteed that (n >= i) */ bytestocopy = (chunksize < (unsigned int)(n - i))?chunksize:(unsigned int)(n - i); if((content_buf_used + bytestocopy) > content_buf_len) { char * tmp; if((content_length >= 0) && ((unsigned int)content_length >= (content_buf_used + bytestocopy))) { content_buf_len = content_length; } else { content_buf_len = content_buf_used + bytestocopy; } tmp = realloc(content_buf, content_buf_len); if(tmp == NULL) { /* memory allocation error */ free(content_buf); free(header_buf); *size = -1; return NULL; } content_buf = tmp; } memcpy(content_buf + content_buf_used, buf + i, bytestocopy); content_buf_used += bytestocopy; i += bytestocopy; chunksize -= bytestocopy; } } else { /* not chunked */ if(content_length > 0 && (content_buf_used + n) > (unsigned int)content_length) { /* skipping additional bytes */ n = content_length - content_buf_used; } if(content_buf_used + n > content_buf_len) { char * tmp; if(content_length >= 0 && (unsigned int)content_length >= (content_buf_used + n)) { content_buf_len = content_length; } else { content_buf_len = content_buf_used + n; } tmp = realloc(content_buf, content_buf_len); if(tmp == NULL) { /* memory allocation error */ free(content_buf); free(header_buf); *size = -1; return NULL; } content_buf = tmp; } memcpy(content_buf + content_buf_used, buf, n); content_buf_used += n; } /* use the Content-Length header value if available */ if(content_length > 0 && content_buf_used >= (unsigned int)content_length) { #ifdef DEBUG printf("End of HTTP content\n"); #endif break; } } end_of_stream: free(header_buf); *size = content_buf_used; if(content_buf_used == 0) { free(content_buf); content_buf = NULL; } return content_buf; } /* miniwget3() : * do all the work. * Return NULL if something failed. */ static void * miniwget3(const char * host, unsigned short port, const char * path, int * size, char * addr_str, int addr_str_len, const char * httpversion, unsigned int scope_id, int * status_code) { char buf[2048]; SOCKET s; int n; int len; int sent; void * content; *size = 0; s = connecthostport(host, port, scope_id); if(ISINVALID(s)) return NULL; /* get address for caller ! */ if(addr_str) { struct sockaddr_storage saddr; socklen_t saddrlen; saddrlen = sizeof(saddr); if(getsockname(s, (struct sockaddr *)&saddr, &saddrlen) < 0) { perror("getsockname"); } else { #if defined(__amigaos__) && !defined(__amigaos4__) /* using INT WINAPI WSAAddressToStringA(LPSOCKADDR, DWORD, LPWSAPROTOCOL_INFOA, LPSTR, LPDWORD); * But his function make a string with the port : nn.nn.nn.nn:port */ /* if(WSAAddressToStringA((SOCKADDR *)&saddr, sizeof(saddr), NULL, addr_str, (DWORD *)&addr_str_len)) { printf("WSAAddressToStringA() failed : %d\n", WSAGetLastError()); }*/ /* the following code is only compatible with ip v4 addresses */ strncpy(addr_str, inet_ntoa(((struct sockaddr_in *)&saddr)->sin_addr), addr_str_len); #else #if 0 if(saddr.sa_family == AF_INET6) { inet_ntop(AF_INET6, &(((struct sockaddr_in6 *)&saddr)->sin6_addr), addr_str, addr_str_len); } else { inet_ntop(AF_INET, &(((struct sockaddr_in *)&saddr)->sin_addr), addr_str, addr_str_len); } #endif /* getnameinfo return ip v6 address with the scope identifier * such as : 2a01:e35:8b2b:7330::%4281128194 */ n = getnameinfo((const struct sockaddr *)&saddr, saddrlen, addr_str, addr_str_len, NULL, 0, NI_NUMERICHOST | NI_NUMERICSERV); if(n != 0) { #ifdef _WIN32 fprintf(stderr, "getnameinfo() failed : %d\n", n); #else fprintf(stderr, "getnameinfo() failed : %s\n", gai_strerror(n)); #endif } #endif } #ifdef DEBUG printf("address miniwget : %s\n", addr_str); #endif } len = snprintf(buf, sizeof(buf), "GET %s HTTP/%s\r\n" "Host: %s:%d\r\n" "Connection: Close\r\n" "User-Agent: " OS_STRING ", " UPNP_VERSION_STRING ", MiniUPnPc/" MINIUPNPC_VERSION_STRING "\r\n" "\r\n", path, httpversion, host, port); if ((unsigned int)len >= sizeof(buf)) { closesocket(s); return NULL; } sent = 0; /* sending the HTTP request */ while(sent < len) { n = send(s, buf+sent, len-sent, 0); if(n < 0) { perror("send"); closesocket(s); return NULL; } else { sent += n; } } content = getHTTPResponse(s, size, status_code); closesocket(s); return content; } /* miniwget2() : * Call miniwget3(); retry with HTTP/1.1 if 1.0 fails. */ static void * miniwget2(const char * host, unsigned short port, const char * path, int * size, char * addr_str, int addr_str_len, unsigned int scope_id, int * status_code) { char * respbuffer; #if 1 respbuffer = miniwget3(host, port, path, size, addr_str, addr_str_len, "1.1", scope_id, status_code); #else respbuffer = miniwget3(host, port, path, size, addr_str, addr_str_len, "1.0", scope_id, status_code); if (*size == 0) { #ifdef DEBUG printf("Retrying with HTTP/1.1\n"); #endif free(respbuffer); respbuffer = miniwget3(host, port, path, size, addr_str, addr_str_len, "1.1", scope_id, status_code); } #endif return respbuffer; } /* parseURL() * arguments : * url : source string not modified * hostname : hostname destination string (size of MAXHOSTNAMELEN+1) * port : port (destination) * path : pointer to the path part of the URL * * Return values : * 0 - Failure * 1 - Success */ int parseURL(const char * url, char * hostname, unsigned short * port, char * * path, unsigned int * scope_id) { char * p1, *p2, *p3; if(!url) return 0; p1 = strstr(url, "://"); if(!p1) return 0; p1 += 3; if( (url[0]!='h') || (url[1]!='t') ||(url[2]!='t') || (url[3]!='p')) return 0; memset(hostname, 0, MAXHOSTNAMELEN + 1); if(*p1 == '[') { /* IP v6 : http://[2a00:1450:8002::6a]/path/abc */ char * scope; scope = strchr(p1, '%'); p2 = strchr(p1, ']'); if(p2 && scope && scope < p2 && scope_id) { /* parse scope */ #ifdef IF_NAMESIZE char tmp[IF_NAMESIZE]; int l; scope++; /* "%25" is just '%' in URL encoding */ if(scope[0] == '2' && scope[1] == '5') scope += 2; /* skip "25" */ l = p2 - scope; if(l >= IF_NAMESIZE) l = IF_NAMESIZE - 1; memcpy(tmp, scope, l); tmp[l] = '\0'; *scope_id = if_nametoindex(tmp); if(*scope_id == 0) { *scope_id = (unsigned int)strtoul(tmp, NULL, 10); } #else /* under windows, scope is numerical */ char tmp[8]; size_t l; scope++; /* "%25" is just '%' in URL encoding */ if(scope[0] == '2' && scope[1] == '5') scope += 2; /* skip "25" */ l = p2 - scope; if(l >= sizeof(tmp)) l = sizeof(tmp) - 1; memcpy(tmp, scope, l); tmp[l] = '\0'; *scope_id = (unsigned int)strtoul(tmp, NULL, 10); #endif } p3 = strchr(p1, '/'); if(p2 && p3) { p2++; strncpy(hostname, p1, MIN(MAXHOSTNAMELEN, (int)(p2-p1))); if(*p2 == ':') { *port = 0; p2++; while( (*p2 >= '0') && (*p2 <= '9')) { *port *= 10; *port += (unsigned short)(*p2 - '0'); p2++; } } else { *port = 80; } *path = p3; return 1; } } p2 = strchr(p1, ':'); p3 = strchr(p1, '/'); if(!p3) return 0; if(!p2 || (p2>p3)) { strncpy(hostname, p1, MIN(MAXHOSTNAMELEN, (int)(p3-p1))); *port = 80; } else { strncpy(hostname, p1, MIN(MAXHOSTNAMELEN, (int)(p2-p1))); *port = 0; p2++; while( (*p2 >= '0') && (*p2 <= '9')) { *port *= 10; *port += (unsigned short)(*p2 - '0'); p2++; } } *path = p3; return 1; } void * miniwget(const char * url, int * size, unsigned int scope_id, int * status_code) { unsigned short port; char * path; /* protocol://host:port/chemin */ char hostname[MAXHOSTNAMELEN+1]; *size = 0; if(!parseURL(url, hostname, &port, &path, &scope_id)) return NULL; #ifdef DEBUG printf("parsed url : hostname='%s' port=%hu path='%s' scope_id=%u\n", hostname, port, path, scope_id); #endif return miniwget2(hostname, port, path, size, 0, 0, scope_id, status_code); } void * miniwget_getaddr(const char * url, int * size, char * addr, int addrlen, unsigned int scope_id, int * status_code) { unsigned short port; char * path; /* protocol://host:port/path */ char hostname[MAXHOSTNAMELEN+1]; *size = 0; if(addr) addr[0] = '\0'; if(!parseURL(url, hostname, &port, &path, &scope_id)) return NULL; #ifdef DEBUG printf("parsed url : hostname='%s' port=%hu path='%s' scope_id=%u\n", hostname, port, path, scope_id); #endif return miniwget2(hostname, port, path, size, addr, addrlen, scope_id, status_code); } opengnb-ver1.6.0.a/libs/miniupnpc/miniwget.h000066400000000000000000000012621500454252100210300ustar00rootroot00000000000000/* $Id: miniwget.h,v 1.13 2018/04/06 10:53:15 nanard Exp $ */ /* Project : miniupnp * Author : Thomas Bernard * Copyright (c) 2005-2016 Thomas Bernard * This software is subject to the conditions detailed in the * LICENCE file provided in this distribution. * */ #ifndef MINIWGET_H_INCLUDED #define MINIWGET_H_INCLUDED #include "miniupnpc_declspec.h" #ifdef __cplusplus extern "C" { #endif MINIUPNP_LIBSPEC void * miniwget(const char *, int *, unsigned int, int *); MINIUPNP_LIBSPEC void * miniwget_getaddr(const char *, int *, char *, int, unsigned int, int *); int parseURL(const char *, char *, unsigned short *, char * *, unsigned int *); #ifdef __cplusplus } #endif #endif opengnb-ver1.6.0.a/libs/miniupnpc/miniwget_private.h000066400000000000000000000007041500454252100225620ustar00rootroot00000000000000/* $Id: miniwget_private.h,v 1.1 2018/04/06 10:17:58 nanard Exp $ */ /* Project : miniupnp * Author : Thomas Bernard * Copyright (c) 2018 Thomas Bernard * This software is subject to the conditions detailed in the * LICENCE file provided in this distribution. * */ #ifndef MINIWGET_INTERNAL_H_INCLUDED #define MINIWGET_INTERNAL_H_INCLUDED #include "miniupnpc_socketdef.h" void * getHTTPResponse(SOCKET s, int * size, int * status_code); #endif opengnb-ver1.6.0.a/libs/miniupnpc/minixml.c000066400000000000000000000132321500454252100206550ustar00rootroot00000000000000/* $Id: minixml.c,v 1.12 2017/12/12 11:17:40 nanard Exp $ */ /* vim: tabstop=4 shiftwidth=4 noexpandtab * minixml.c : the minimum size a xml parser can be ! */ /* Project : miniupnp * webpage: http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ * Author : Thomas Bernard Copyright (c) 2005-2017, Thomas BERNARD All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * 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. * The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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. */ #include #include "minixml.h" /* parseatt : used to parse the argument list * return 0 (false) in case of success and -1 (true) if the end * of the xmlbuffer is reached. */ static int parseatt(struct xmlparser * p) { const char * attname; int attnamelen; const char * attvalue; int attvaluelen; while(p->xml < p->xmlend) { if(*p->xml=='/' || *p->xml=='>') return 0; if( !IS_WHITE_SPACE(*p->xml) ) { char sep; attname = p->xml; attnamelen = 0; while(*p->xml!='=' && !IS_WHITE_SPACE(*p->xml) ) { attnamelen++; p->xml++; if(p->xml >= p->xmlend) return -1; } while(*(p->xml++) != '=') { if(p->xml >= p->xmlend) return -1; } while(IS_WHITE_SPACE(*p->xml)) { p->xml++; if(p->xml >= p->xmlend) return -1; } sep = *p->xml; if(sep=='\'' || sep=='\"') { p->xml++; if(p->xml >= p->xmlend) return -1; attvalue = p->xml; attvaluelen = 0; while(*p->xml != sep) { attvaluelen++; p->xml++; if(p->xml >= p->xmlend) return -1; } } else { attvalue = p->xml; attvaluelen = 0; while( !IS_WHITE_SPACE(*p->xml) && *p->xml != '>' && *p->xml != '/') { attvaluelen++; p->xml++; if(p->xml >= p->xmlend) return -1; } } /*printf("%.*s='%.*s'\n", attnamelen, attname, attvaluelen, attvalue);*/ if(p->attfunc) p->attfunc(p->data, attname, attnamelen, attvalue, attvaluelen); } p->xml++; } return -1; } /* parseelt parse the xml stream and * call the callback functions when needed... */ static void parseelt(struct xmlparser * p) { int i; const char * elementname; while(p->xml < (p->xmlend - 1)) { if((p->xml + 4) <= p->xmlend && (0 == memcmp(p->xml, "", 3) != 0); p->xml += 3; } else if((p->xml)[0]=='<' && (p->xml)[1]!='?') { i = 0; elementname = ++p->xml; while( !IS_WHITE_SPACE(*p->xml) && (*p->xml!='>') && (*p->xml!='/') ) { i++; p->xml++; if (p->xml >= p->xmlend) return; /* to ignore namespace : */ if(*p->xml==':') { i = 0; elementname = ++p->xml; } } if(i>0) { if(p->starteltfunc) p->starteltfunc(p->data, elementname, i); if(parseatt(p)) return; if(*p->xml!='/') { const char * data; i = 0; data = ++p->xml; if (p->xml >= p->xmlend) return; while( IS_WHITE_SPACE(*p->xml) ) { i++; p->xml++; if (p->xml >= p->xmlend) return; } /* CDATA are at least 9 + 3 characters long : */ if((p->xmlend >= (p->xml + (9 + 3))) && (memcmp(p->xml, "xml += 9; data = p->xml; i = 0; while(memcmp(p->xml, "]]>", 3) != 0) { i++; p->xml++; if ((p->xml + 3) >= p->xmlend) return; } if(i>0 && p->datafunc) p->datafunc(p->data, data, i); while(*p->xml!='<') { p->xml++; if (p->xml >= p->xmlend) return; } } else { while(*p->xml!='<') { i++; p->xml++; if ((p->xml + 1) >= p->xmlend) return; } if(i>0 && p->datafunc && *(p->xml + 1) == '/') p->datafunc(p->data, data, i); } } } else if(*p->xml == '/') { i = 0; elementname = ++p->xml; if (p->xml >= p->xmlend) return; while((*p->xml != '>')) { i++; p->xml++; if (p->xml >= p->xmlend) return; } if(p->endeltfunc) p->endeltfunc(p->data, elementname, i); p->xml++; } } else { p->xml++; } } } /* the parser must be initialized before calling this function */ void parsexml(struct xmlparser * parser) { parser->xml = parser->xmlstart; parser->xmlend = parser->xmlstart + parser->xmlsize; parseelt(parser); } opengnb-ver1.6.0.a/libs/miniupnpc/minixml.h000066400000000000000000000022331500454252100206610ustar00rootroot00000000000000/* $Id: minixml.h,v 1.8 2019/02/10 12:29:25 nanard Exp $ */ /* minimal xml parser * * Project : miniupnp * Website : http://miniupnp.free.fr/ * Author : Thomas Bernard * Copyright (c) 2005 Thomas Bernard * This software is subject to the conditions detailed in the * LICENCE file provided in this distribution. * */ #ifndef MINIXML_H_INCLUDED #define MINIXML_H_INCLUDED #define IS_WHITE_SPACE(c) ((c)==' ' || (c)=='\t' || (c)=='\r' || (c)=='\n') /* if a callback function pointer is set to NULL, * the function is not called */ struct xmlparser { const char *xmlstart; const char *xmlend; const char *xml; /* pointer to current character */ int xmlsize; void * data; void (*starteltfunc) (void *, const char *, int); void (*endeltfunc) (void *, const char *, int); void (*datafunc) (void *, const char *, int); void (*attfunc) (void *, const char *, int, const char *, int); }; /* parsexml() * the xmlparser structure must be initialized before the call * the following structure members have to be initialized : * xmlstart, xmlsize, data, *func * xml is for internal usage, xmlend is computed automatically */ void parsexml(struct xmlparser *); #endif opengnb-ver1.6.0.a/libs/miniupnpc/portlistingparse.c000066400000000000000000000073431500454252100226170ustar00rootroot00000000000000/* $Id: portlistingparse.c,v 1.10 2016/12/16 08:53:21 nanard Exp $ */ /* MiniUPnP project * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ * (c) 2011-2016 Thomas Bernard * This software is subject to the conditions detailed * in the LICENCE file provided within the distribution */ #include #include #ifdef DEBUG #include #endif /* DEBUG */ #include "portlistingparse.h" #include "minixml.h" /* list of the elements */ static const struct { const portMappingElt code; const char * const str; } elements[] = { { PortMappingEntry, "PortMappingEntry"}, { NewRemoteHost, "NewRemoteHost"}, { NewExternalPort, "NewExternalPort"}, { NewProtocol, "NewProtocol"}, { NewInternalPort, "NewInternalPort"}, { NewInternalClient, "NewInternalClient"}, { NewEnabled, "NewEnabled"}, { NewDescription, "NewDescription"}, { NewLeaseTime, "NewLeaseTime"}, { PortMappingEltNone, NULL} }; /* Helper function */ static UNSIGNED_INTEGER atoui(const char * p, int l) { UNSIGNED_INTEGER r = 0; while(l > 0 && *p) { if(*p >= '0' && *p <= '9') r = r*10 + (*p - '0'); else break; p++; l--; } return r; } /* Start element handler */ static void startelt(void * d, const char * name, int l) { int i; struct PortMappingParserData * pdata = (struct PortMappingParserData *)d; pdata->curelt = PortMappingEltNone; for(i = 0; elements[i].str; i++) { if(strlen(elements[i].str) == (size_t)l && memcmp(name, elements[i].str, l) == 0) { pdata->curelt = elements[i].code; break; } } if(pdata->curelt == PortMappingEntry) { struct PortMapping * pm; pm = calloc(1, sizeof(struct PortMapping)); if(pm == NULL) { /* malloc error */ #ifdef DEBUG fprintf(stderr, "%s: error allocating memory", "startelt"); #endif /* DEBUG */ return; } pm->l_next = pdata->l_head; /* insert in list */ pdata->l_head = pm; } } /* End element handler */ static void endelt(void * d, const char * name, int l) { struct PortMappingParserData * pdata = (struct PortMappingParserData *)d; (void)name; (void)l; pdata->curelt = PortMappingEltNone; } /* Data handler */ static void data(void * d, const char * data, int l) { struct PortMapping * pm; struct PortMappingParserData * pdata = (struct PortMappingParserData *)d; pm = pdata->l_head; if(!pm) return; if(l > 63) l = 63; switch(pdata->curelt) { case NewRemoteHost: memcpy(pm->remoteHost, data, l); pm->remoteHost[l] = '\0'; break; case NewExternalPort: pm->externalPort = (unsigned short)atoui(data, l); break; case NewProtocol: if(l > 3) l = 3; memcpy(pm->protocol, data, l); pm->protocol[l] = '\0'; break; case NewInternalPort: pm->internalPort = (unsigned short)atoui(data, l); break; case NewInternalClient: memcpy(pm->internalClient, data, l); pm->internalClient[l] = '\0'; break; case NewEnabled: pm->enabled = (unsigned char)atoui(data, l); break; case NewDescription: memcpy(pm->description, data, l); pm->description[l] = '\0'; break; case NewLeaseTime: pm->leaseTime = atoui(data, l); break; default: break; } } /* Parse the PortMappingList XML document for IGD version 2 */ void ParsePortListing(const char * buffer, int bufsize, struct PortMappingParserData * pdata) { struct xmlparser parser; memset(pdata, 0, sizeof(struct PortMappingParserData)); /* init xmlparser */ parser.xmlstart = buffer; parser.xmlsize = bufsize; parser.data = pdata; parser.starteltfunc = startelt; parser.endeltfunc = endelt; parser.datafunc = data; parser.attfunc = 0; parsexml(&parser); } void FreePortListing(struct PortMappingParserData * pdata) { struct PortMapping * pm; while((pm = pdata->l_head) != NULL) { /* remove from list */ pdata->l_head = pm->l_next; free(pm); } } opengnb-ver1.6.0.a/libs/miniupnpc/portlistingparse.h000066400000000000000000000034461500454252100226240ustar00rootroot00000000000000/* $Id: portlistingparse.h,v 1.11 2015/07/21 13:16:55 nanard Exp $ */ /* MiniUPnP project * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ * (c) 2011-2015 Thomas Bernard * This software is subject to the conditions detailed * in the LICENCE file provided within the distribution */ #ifndef PORTLISTINGPARSE_H_INCLUDED #define PORTLISTINGPARSE_H_INCLUDED #include "miniupnpc_declspec.h" /* for the definition of UNSIGNED_INTEGER */ #include "miniupnpctypes.h" #ifdef __cplusplus extern "C" { #endif /* sample of PortMappingEntry : 202.233.2.1 2345 TCP 2345 192.168.1.137 1 dooom 345 */ typedef enum { PortMappingEltNone, PortMappingEntry, NewRemoteHost, NewExternalPort, NewProtocol, NewInternalPort, NewInternalClient, NewEnabled, NewDescription, NewLeaseTime } portMappingElt; struct PortMapping { struct PortMapping * l_next; /* list next element */ UNSIGNED_INTEGER leaseTime; unsigned short externalPort; unsigned short internalPort; char remoteHost[64]; char internalClient[64]; char description[64]; char protocol[4]; unsigned char enabled; }; struct PortMappingParserData { struct PortMapping * l_head; /* list head */ portMappingElt curelt; }; MINIUPNP_LIBSPEC void ParsePortListing(const char * buffer, int bufsize, struct PortMappingParserData * pdata); MINIUPNP_LIBSPEC void FreePortListing(struct PortMappingParserData * pdata); #ifdef __cplusplus } #endif #endif opengnb-ver1.6.0.a/libs/miniupnpc/receivedata.c000066400000000000000000000056651500454252100214670ustar00rootroot00000000000000/* $Id: receivedata.c,v 1.9 2018/04/06 10:53:15 nanard Exp $ */ /* Project : miniupnp * Website : http://miniupnp.free.fr/ * Author : Thomas Bernard * Copyright (c) 2011-2014 Thomas Bernard * This software is subject to the conditions detailed in the * LICENCE file provided in this distribution. */ #include #include #ifdef _WIN32 #include #include #else /* _WIN32 */ #include #if defined(__amigaos__) && !defined(__amigaos4__) #define socklen_t int #else /* #if defined(__amigaos__) && !defined(__amigaos4__) */ #include #endif /* #else defined(__amigaos__) && !defined(__amigaos4__) */ #include #include #if !defined(__amigaos__) && !defined(__amigaos4__) #include #endif /* !defined(__amigaos__) && !defined(__amigaos4__) */ #include #define MINIUPNPC_IGNORE_EINTR #endif /* _WIN32 */ #include "receivedata.h" int receivedata(SOCKET socket, char * data, int length, int timeout, unsigned int * scope_id) { #ifdef MINIUPNPC_GET_SRC_ADDR struct sockaddr_storage src_addr; socklen_t src_addr_len = sizeof(src_addr); #endif /* MINIUPNPC_GET_SRC_ADDR */ int n; #if !defined(_WIN32) && !defined(__amigaos__) && !defined(__amigaos4__) /* using poll */ struct pollfd fds[1]; /* for the poll */ #ifdef MINIUPNPC_IGNORE_EINTR do { #endif /* MINIUPNPC_IGNORE_EINTR */ fds[0].fd = socket; fds[0].events = POLLIN; n = poll(fds, 1, timeout); #ifdef MINIUPNPC_IGNORE_EINTR } while(n < 0 && errno == EINTR); #endif /* MINIUPNPC_IGNORE_EINTR */ if(n < 0) { PRINT_SOCKET_ERROR("poll"); return -1; } else if(n == 0) { /* timeout */ return 0; } #else /* !defined(_WIN32) && !defined(__amigaos__) && !defined(__amigaos4__) */ /* using select under _WIN32 and amigaos */ fd_set socketSet; TIMEVAL timeval; FD_ZERO(&socketSet); FD_SET(socket, &socketSet); timeval.tv_sec = timeout / 1000; timeval.tv_usec = (timeout % 1000) * 1000; n = select(FD_SETSIZE, &socketSet, NULL, NULL, &timeval); if(n < 0) { PRINT_SOCKET_ERROR("select"); return -1; } else if(n == 0) { return 0; } #endif /* !defined(_WIN32) && !defined(__amigaos__) && !defined(__amigaos4__) */ #ifdef MINIUPNPC_GET_SRC_ADDR memset(&src_addr, 0, sizeof(src_addr)); n = recvfrom(socket, data, length, 0, (struct sockaddr *)&src_addr, &src_addr_len); #else /* MINIUPNPC_GET_SRC_ADDR */ n = recv(socket, data, length, 0); #endif /* MINIUPNPC_GET_SRC_ADDR */ if(n<0) { PRINT_SOCKET_ERROR("recv"); } #ifdef MINIUPNPC_GET_SRC_ADDR if (src_addr.ss_family == AF_INET6) { const struct sockaddr_in6 * src_addr6 = (struct sockaddr_in6 *)&src_addr; #ifdef DEBUG printf("scope_id=%u\n", src_addr6->sin6_scope_id); #endif /* DEBUG */ if(scope_id) *scope_id = src_addr6->sin6_scope_id; } #endif /* MINIUPNPC_GET_SRC_ADDR */ return n; } opengnb-ver1.6.0.a/libs/miniupnpc/receivedata.h000066400000000000000000000013551500454252100214640ustar00rootroot00000000000000/* $Id: receivedata.h,v 1.5 2018/04/06 10:53:15 nanard Exp $ */ /* Project: miniupnp * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ * Author: Thomas Bernard * Copyright (c) 2011-2018 Thomas Bernard * This software is subjects to the conditions detailed * in the LICENCE file provided within this distribution */ #ifndef RECEIVEDATA_H_INCLUDED #define RECEIVEDATA_H_INCLUDED #include "miniupnpc_socketdef.h" /* Reads data from the specified socket. * Returns the number of bytes read if successful, zero if no bytes were * read or if we timed out. Returns negative if there was an error. */ int receivedata(SOCKET socket, char * data, int length, int timeout, unsigned int * scope_id); #endif opengnb-ver1.6.0.a/libs/miniupnpc/upnpcommands.c000066400000000000000000001045331500454252100217110ustar00rootroot00000000000000/* $Id: upnpcommands.c,v 1.51 2019/04/23 11:45:15 nanard Exp $ */ /* vim: tabstop=4 shiftwidth=4 noexpandtab * Project : miniupnp * Author : Thomas Bernard * Copyright (c) 2005-2018 Thomas Bernard * This software is subject to the conditions detailed in the * LICENCE file provided in this distribution. * */ #include #include #include #include "upnpcommands.h" #include "miniupnpc.h" #include "portlistingparse.h" #include "upnpreplyparse.h" static UNSIGNED_INTEGER my_atoui(const char * s) { return s ? ((UNSIGNED_INTEGER)STRTOUI(s, NULL, 0)) : 0; } /* * */ MINIUPNP_LIBSPEC UNSIGNED_INTEGER UPNP_GetTotalBytesSent(const char * controlURL, const char * servicetype) { struct NameValueParserData pdata; char * buffer; int bufsize; unsigned int r = 0; char * p; if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype, "GetTotalBytesSent", 0, &bufsize))) { return (UNSIGNED_INTEGER)UPNPCOMMAND_HTTP_ERROR; } ParseNameValue(buffer, bufsize, &pdata); /*DisplayNameValueList(buffer, bufsize);*/ free(buffer); p = GetValueFromNameValueList(&pdata, "NewTotalBytesSent"); r = my_atoui(p); ClearNameValueList(&pdata); return r; } /* * */ MINIUPNP_LIBSPEC UNSIGNED_INTEGER UPNP_GetTotalBytesReceived(const char * controlURL, const char * servicetype) { struct NameValueParserData pdata; char * buffer; int bufsize; unsigned int r = 0; char * p; if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype, "GetTotalBytesReceived", 0, &bufsize))) { return (UNSIGNED_INTEGER)UPNPCOMMAND_HTTP_ERROR; } ParseNameValue(buffer, bufsize, &pdata); /*DisplayNameValueList(buffer, bufsize);*/ free(buffer); p = GetValueFromNameValueList(&pdata, "NewTotalBytesReceived"); r = my_atoui(p); ClearNameValueList(&pdata); return r; } /* * */ MINIUPNP_LIBSPEC UNSIGNED_INTEGER UPNP_GetTotalPacketsSent(const char * controlURL, const char * servicetype) { struct NameValueParserData pdata; char * buffer; int bufsize; unsigned int r = 0; char * p; if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype, "GetTotalPacketsSent", 0, &bufsize))) { return (UNSIGNED_INTEGER)UPNPCOMMAND_HTTP_ERROR; } ParseNameValue(buffer, bufsize, &pdata); /*DisplayNameValueList(buffer, bufsize);*/ free(buffer); p = GetValueFromNameValueList(&pdata, "NewTotalPacketsSent"); r = my_atoui(p); ClearNameValueList(&pdata); return r; } /* * */ MINIUPNP_LIBSPEC UNSIGNED_INTEGER UPNP_GetTotalPacketsReceived(const char * controlURL, const char * servicetype) { struct NameValueParserData pdata; char * buffer; int bufsize; unsigned int r = 0; char * p; if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype, "GetTotalPacketsReceived", 0, &bufsize))) { return (UNSIGNED_INTEGER)UPNPCOMMAND_HTTP_ERROR; } ParseNameValue(buffer, bufsize, &pdata); /*DisplayNameValueList(buffer, bufsize);*/ free(buffer); p = GetValueFromNameValueList(&pdata, "NewTotalPacketsReceived"); r = my_atoui(p); ClearNameValueList(&pdata); return r; } /* UPNP_GetStatusInfo() call the corresponding UPNP method * returns the current status and uptime */ MINIUPNP_LIBSPEC int UPNP_GetStatusInfo(const char * controlURL, const char * servicetype, char * status, unsigned int * uptime, char * lastconnerror) { struct NameValueParserData pdata; char * buffer; int bufsize; char * p; char * up; char * err; int ret = UPNPCOMMAND_UNKNOWN_ERROR; if(!status && !uptime) return UPNPCOMMAND_INVALID_ARGS; if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype, "GetStatusInfo", 0, &bufsize))) { return UPNPCOMMAND_HTTP_ERROR; } ParseNameValue(buffer, bufsize, &pdata); /*DisplayNameValueList(buffer, bufsize);*/ free(buffer); up = GetValueFromNameValueList(&pdata, "NewUptime"); p = GetValueFromNameValueList(&pdata, "NewConnectionStatus"); err = GetValueFromNameValueList(&pdata, "NewLastConnectionError"); if(p && up) ret = UPNPCOMMAND_SUCCESS; if(status) { if(p){ strncpy(status, p, 64 ); status[63] = '\0'; }else status[0]= '\0'; } if(uptime) { if(up) sscanf(up,"%u",uptime); else *uptime = 0; } if(lastconnerror) { if(err) { strncpy(lastconnerror, err, 64 ); lastconnerror[63] = '\0'; } else lastconnerror[0] = '\0'; } p = GetValueFromNameValueList(&pdata, "errorCode"); if(p) { ret = UPNPCOMMAND_UNKNOWN_ERROR; sscanf(p, "%d", &ret); } ClearNameValueList(&pdata); return ret; } /* UPNP_GetConnectionTypeInfo() call the corresponding UPNP method * returns the connection type */ MINIUPNP_LIBSPEC int UPNP_GetConnectionTypeInfo(const char * controlURL, const char * servicetype, char * connectionType) { struct NameValueParserData pdata; char * buffer; int bufsize; char * p; int ret = UPNPCOMMAND_UNKNOWN_ERROR; if(!connectionType) return UPNPCOMMAND_INVALID_ARGS; if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype, "GetConnectionTypeInfo", 0, &bufsize))) { return UPNPCOMMAND_HTTP_ERROR; } ParseNameValue(buffer, bufsize, &pdata); free(buffer); p = GetValueFromNameValueList(&pdata, "NewConnectionType"); /*p = GetValueFromNameValueList(&pdata, "NewPossibleConnectionTypes");*/ /* PossibleConnectionTypes will have several values.... */ if(p) { strncpy(connectionType, p, 64 ); connectionType[63] = '\0'; ret = UPNPCOMMAND_SUCCESS; } else connectionType[0] = '\0'; p = GetValueFromNameValueList(&pdata, "errorCode"); if(p) { ret = UPNPCOMMAND_UNKNOWN_ERROR; sscanf(p, "%d", &ret); } ClearNameValueList(&pdata); return ret; } /* UPNP_GetLinkLayerMaxBitRate() call the corresponding UPNP method. * Returns 2 values: Downloadlink bandwidth and Uplink bandwidth. * One of the values can be null * Note : GetLinkLayerMaxBitRates belongs to WANPPPConnection:1 only * We can use the GetCommonLinkProperties from WANCommonInterfaceConfig:1 */ MINIUPNP_LIBSPEC int UPNP_GetLinkLayerMaxBitRates(const char * controlURL, const char * servicetype, unsigned int * bitrateDown, unsigned int * bitrateUp) { struct NameValueParserData pdata; char * buffer; int bufsize; int ret = UPNPCOMMAND_UNKNOWN_ERROR; char * down; char * up; char * p; if(!bitrateDown && !bitrateUp) return UPNPCOMMAND_INVALID_ARGS; /* shouldn't we use GetCommonLinkProperties ? */ if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype, "GetCommonLinkProperties", 0, &bufsize))) { /*"GetLinkLayerMaxBitRates", 0, &bufsize);*/ return UPNPCOMMAND_HTTP_ERROR; } /*DisplayNameValueList(buffer, bufsize);*/ ParseNameValue(buffer, bufsize, &pdata); free(buffer); /*down = GetValueFromNameValueList(&pdata, "NewDownstreamMaxBitRate");*/ /*up = GetValueFromNameValueList(&pdata, "NewUpstreamMaxBitRate");*/ down = GetValueFromNameValueList(&pdata, "NewLayer1DownstreamMaxBitRate"); up = GetValueFromNameValueList(&pdata, "NewLayer1UpstreamMaxBitRate"); /*GetValueFromNameValueList(&pdata, "NewWANAccessType");*/ /*GetValueFromNameValueList(&pdata, "NewPhysicalLinkStatus");*/ if(down && up) ret = UPNPCOMMAND_SUCCESS; if(bitrateDown) { if(down) sscanf(down,"%u",bitrateDown); else *bitrateDown = 0; } if(bitrateUp) { if(up) sscanf(up,"%u",bitrateUp); else *bitrateUp = 0; } p = GetValueFromNameValueList(&pdata, "errorCode"); if(p) { ret = UPNPCOMMAND_UNKNOWN_ERROR; sscanf(p, "%d", &ret); } ClearNameValueList(&pdata); return ret; } /* UPNP_GetExternalIPAddress() call the corresponding UPNP method. * if the third arg is not null the value is copied to it. * at least 16 bytes must be available * * Return values : * 0 : SUCCESS * NON ZERO : ERROR Either an UPnP error code or an unknown error. * * 402 Invalid Args - See UPnP Device Architecture section on Control. * 501 Action Failed - See UPnP Device Architecture section on Control. */ MINIUPNP_LIBSPEC int UPNP_GetExternalIPAddress(const char * controlURL, const char * servicetype, char * extIpAdd) { struct NameValueParserData pdata; char * buffer; int bufsize; char * p; int ret = UPNPCOMMAND_UNKNOWN_ERROR; if(!extIpAdd || !controlURL || !servicetype) return UPNPCOMMAND_INVALID_ARGS; if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype, "GetExternalIPAddress", 0, &bufsize))) { return UPNPCOMMAND_HTTP_ERROR; } /*DisplayNameValueList(buffer, bufsize);*/ ParseNameValue(buffer, bufsize, &pdata); free(buffer); /*printf("external ip = %s\n", GetValueFromNameValueList(&pdata, "NewExternalIPAddress") );*/ p = GetValueFromNameValueList(&pdata, "NewExternalIPAddress"); if(p) { strncpy(extIpAdd, p, 16 ); extIpAdd[15] = '\0'; ret = UPNPCOMMAND_SUCCESS; } else extIpAdd[0] = '\0'; p = GetValueFromNameValueList(&pdata, "errorCode"); if(p) { ret = UPNPCOMMAND_UNKNOWN_ERROR; sscanf(p, "%d", &ret); } ClearNameValueList(&pdata); return ret; } MINIUPNP_LIBSPEC int UPNP_AddPortMapping(const char * controlURL, const char * servicetype, const char * extPort, const char * inPort, const char * inClient, const char * desc, const char * proto, const char * remoteHost, const char * leaseDuration) { struct UPNParg * AddPortMappingArgs; char * buffer; int bufsize; struct NameValueParserData pdata; const char * resVal; int ret; if(!inPort || !inClient || !proto || !extPort) return UPNPCOMMAND_INVALID_ARGS; AddPortMappingArgs = calloc(9, sizeof(struct UPNParg)); if(AddPortMappingArgs == NULL) return UPNPCOMMAND_MEM_ALLOC_ERROR; AddPortMappingArgs[0].elt = "NewRemoteHost"; AddPortMappingArgs[0].val = remoteHost; AddPortMappingArgs[1].elt = "NewExternalPort"; AddPortMappingArgs[1].val = extPort; AddPortMappingArgs[2].elt = "NewProtocol"; AddPortMappingArgs[2].val = proto; AddPortMappingArgs[3].elt = "NewInternalPort"; AddPortMappingArgs[3].val = inPort; AddPortMappingArgs[4].elt = "NewInternalClient"; AddPortMappingArgs[4].val = inClient; AddPortMappingArgs[5].elt = "NewEnabled"; AddPortMappingArgs[5].val = "1"; AddPortMappingArgs[6].elt = "NewPortMappingDescription"; AddPortMappingArgs[6].val = desc?desc:"libminiupnpc"; AddPortMappingArgs[7].elt = "NewLeaseDuration"; AddPortMappingArgs[7].val = leaseDuration?leaseDuration:"0"; buffer = simpleUPnPcommand(-1, controlURL, servicetype, "AddPortMapping", AddPortMappingArgs, &bufsize); free(AddPortMappingArgs); if(!buffer) { return UPNPCOMMAND_HTTP_ERROR; } /*DisplayNameValueList(buffer, bufsize);*/ /*buffer[bufsize] = '\0';*/ /*puts(buffer);*/ ParseNameValue(buffer, bufsize, &pdata); free(buffer); resVal = GetValueFromNameValueList(&pdata, "errorCode"); if(resVal) { /*printf("AddPortMapping errorCode = '%s'\n", resVal); */ ret = UPNPCOMMAND_UNKNOWN_ERROR; sscanf(resVal, "%d", &ret); } else { ret = UPNPCOMMAND_SUCCESS; } ClearNameValueList(&pdata); return ret; } MINIUPNP_LIBSPEC int UPNP_AddAnyPortMapping(const char * controlURL, const char * servicetype, const char * extPort, const char * inPort, const char * inClient, const char * desc, const char * proto, const char * remoteHost, const char * leaseDuration, char * reservedPort) { struct UPNParg * AddPortMappingArgs; char * buffer; int bufsize; struct NameValueParserData pdata; const char * resVal; int ret; if(!inPort || !inClient || !proto || !extPort) return UPNPCOMMAND_INVALID_ARGS; AddPortMappingArgs = calloc(9, sizeof(struct UPNParg)); if(AddPortMappingArgs == NULL) return UPNPCOMMAND_MEM_ALLOC_ERROR; AddPortMappingArgs[0].elt = "NewRemoteHost"; AddPortMappingArgs[0].val = remoteHost; AddPortMappingArgs[1].elt = "NewExternalPort"; AddPortMappingArgs[1].val = extPort; AddPortMappingArgs[2].elt = "NewProtocol"; AddPortMappingArgs[2].val = proto; AddPortMappingArgs[3].elt = "NewInternalPort"; AddPortMappingArgs[3].val = inPort; AddPortMappingArgs[4].elt = "NewInternalClient"; AddPortMappingArgs[4].val = inClient; AddPortMappingArgs[5].elt = "NewEnabled"; AddPortMappingArgs[5].val = "1"; AddPortMappingArgs[6].elt = "NewPortMappingDescription"; AddPortMappingArgs[6].val = desc?desc:"libminiupnpc"; AddPortMappingArgs[7].elt = "NewLeaseDuration"; AddPortMappingArgs[7].val = leaseDuration?leaseDuration:"0"; buffer = simpleUPnPcommand(-1, controlURL, servicetype, "AddAnyPortMapping", AddPortMappingArgs, &bufsize); free(AddPortMappingArgs); if(!buffer) { return UPNPCOMMAND_HTTP_ERROR; } ParseNameValue(buffer, bufsize, &pdata); free(buffer); resVal = GetValueFromNameValueList(&pdata, "errorCode"); if(resVal) { ret = UPNPCOMMAND_UNKNOWN_ERROR; sscanf(resVal, "%d", &ret); } else { char *p; p = GetValueFromNameValueList(&pdata, "NewReservedPort"); if(p) { strncpy(reservedPort, p, 6); reservedPort[5] = '\0'; ret = UPNPCOMMAND_SUCCESS; } else { ret = UPNPCOMMAND_INVALID_RESPONSE; } } ClearNameValueList(&pdata); return ret; } MINIUPNP_LIBSPEC int UPNP_DeletePortMapping(const char * controlURL, const char * servicetype, const char * extPort, const char * proto, const char * remoteHost) { /*struct NameValueParserData pdata;*/ struct UPNParg * DeletePortMappingArgs; char * buffer; int bufsize; struct NameValueParserData pdata; const char * resVal; int ret; if(!extPort || !proto) return UPNPCOMMAND_INVALID_ARGS; DeletePortMappingArgs = calloc(4, sizeof(struct UPNParg)); if(DeletePortMappingArgs == NULL) return UPNPCOMMAND_MEM_ALLOC_ERROR; DeletePortMappingArgs[0].elt = "NewRemoteHost"; DeletePortMappingArgs[0].val = remoteHost; DeletePortMappingArgs[1].elt = "NewExternalPort"; DeletePortMappingArgs[1].val = extPort; DeletePortMappingArgs[2].elt = "NewProtocol"; DeletePortMappingArgs[2].val = proto; buffer = simpleUPnPcommand(-1, controlURL, servicetype, "DeletePortMapping", DeletePortMappingArgs, &bufsize); free(DeletePortMappingArgs); if(!buffer) { return UPNPCOMMAND_HTTP_ERROR; } /*DisplayNameValueList(buffer, bufsize);*/ ParseNameValue(buffer, bufsize, &pdata); free(buffer); resVal = GetValueFromNameValueList(&pdata, "errorCode"); if(resVal) { ret = UPNPCOMMAND_UNKNOWN_ERROR; sscanf(resVal, "%d", &ret); } else { ret = UPNPCOMMAND_SUCCESS; } ClearNameValueList(&pdata); return ret; } MINIUPNP_LIBSPEC int UPNP_DeletePortMappingRange(const char * controlURL, const char * servicetype, const char * extPortStart, const char * extPortEnd, const char * proto, const char * manage) { struct UPNParg * DeletePortMappingArgs; char * buffer; int bufsize; struct NameValueParserData pdata; const char * resVal; int ret; if(!extPortStart || !extPortEnd || !proto || !manage) return UPNPCOMMAND_INVALID_ARGS; DeletePortMappingArgs = calloc(5, sizeof(struct UPNParg)); if(DeletePortMappingArgs == NULL) return UPNPCOMMAND_MEM_ALLOC_ERROR; DeletePortMappingArgs[0].elt = "NewStartPort"; DeletePortMappingArgs[0].val = extPortStart; DeletePortMappingArgs[1].elt = "NewEndPort"; DeletePortMappingArgs[1].val = extPortEnd; DeletePortMappingArgs[2].elt = "NewProtocol"; DeletePortMappingArgs[2].val = proto; DeletePortMappingArgs[3].elt = "NewManage"; DeletePortMappingArgs[3].val = manage; buffer = simpleUPnPcommand(-1, controlURL, servicetype, "DeletePortMappingRange", DeletePortMappingArgs, &bufsize); free(DeletePortMappingArgs); if(!buffer) { return UPNPCOMMAND_HTTP_ERROR; } ParseNameValue(buffer, bufsize, &pdata); free(buffer); resVal = GetValueFromNameValueList(&pdata, "errorCode"); if(resVal) { ret = UPNPCOMMAND_UNKNOWN_ERROR; sscanf(resVal, "%d", &ret); } else { ret = UPNPCOMMAND_SUCCESS; } ClearNameValueList(&pdata); return ret; } MINIUPNP_LIBSPEC int UPNP_GetGenericPortMappingEntry(const char * controlURL, const char * servicetype, const char * index, char * extPort, char * intClient, char * intPort, char * protocol, char * desc, char * enabled, char * rHost, char * duration) { struct NameValueParserData pdata; struct UPNParg * GetPortMappingArgs; char * buffer; int bufsize; char * p; int r = UPNPCOMMAND_UNKNOWN_ERROR; if(!index) return UPNPCOMMAND_INVALID_ARGS; intClient[0] = '\0'; intPort[0] = '\0'; GetPortMappingArgs = calloc(2, sizeof(struct UPNParg)); if(GetPortMappingArgs == NULL) return UPNPCOMMAND_MEM_ALLOC_ERROR; GetPortMappingArgs[0].elt = "NewPortMappingIndex"; GetPortMappingArgs[0].val = index; buffer = simpleUPnPcommand(-1, controlURL, servicetype, "GetGenericPortMappingEntry", GetPortMappingArgs, &bufsize); free(GetPortMappingArgs); if(!buffer) { return UPNPCOMMAND_HTTP_ERROR; } ParseNameValue(buffer, bufsize, &pdata); free(buffer); p = GetValueFromNameValueList(&pdata, "NewRemoteHost"); if(p && rHost) { strncpy(rHost, p, 64); rHost[63] = '\0'; } p = GetValueFromNameValueList(&pdata, "NewExternalPort"); if(p && extPort) { strncpy(extPort, p, 6); extPort[5] = '\0'; r = UPNPCOMMAND_SUCCESS; } p = GetValueFromNameValueList(&pdata, "NewProtocol"); if(p && protocol) { strncpy(protocol, p, 4); protocol[3] = '\0'; } p = GetValueFromNameValueList(&pdata, "NewInternalClient"); if(p) { strncpy(intClient, p, 16); intClient[15] = '\0'; r = 0; } p = GetValueFromNameValueList(&pdata, "NewInternalPort"); if(p) { strncpy(intPort, p, 6); intPort[5] = '\0'; } p = GetValueFromNameValueList(&pdata, "NewEnabled"); if(p && enabled) { strncpy(enabled, p, 4); enabled[3] = '\0'; } p = GetValueFromNameValueList(&pdata, "NewPortMappingDescription"); if(p && desc) { strncpy(desc, p, 80); desc[79] = '\0'; } p = GetValueFromNameValueList(&pdata, "NewLeaseDuration"); if(p && duration) { strncpy(duration, p, 16); duration[15] = '\0'; } p = GetValueFromNameValueList(&pdata, "errorCode"); if(p) { r = UPNPCOMMAND_UNKNOWN_ERROR; sscanf(p, "%d", &r); } ClearNameValueList(&pdata); return r; } MINIUPNP_LIBSPEC int UPNP_GetPortMappingNumberOfEntries(const char * controlURL, const char * servicetype, unsigned int * numEntries) { struct NameValueParserData pdata; char * buffer; int bufsize; char* p; int ret = UPNPCOMMAND_UNKNOWN_ERROR; if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype, "GetPortMappingNumberOfEntries", 0, &bufsize))) { return UPNPCOMMAND_HTTP_ERROR; } #ifdef DEBUG DisplayNameValueList(buffer, bufsize); #endif ParseNameValue(buffer, bufsize, &pdata); free(buffer); p = GetValueFromNameValueList(&pdata, "NewPortMappingNumberOfEntries"); if(numEntries && p) { *numEntries = 0; sscanf(p, "%u", numEntries); ret = UPNPCOMMAND_SUCCESS; } p = GetValueFromNameValueList(&pdata, "errorCode"); if(p) { ret = UPNPCOMMAND_UNKNOWN_ERROR; sscanf(p, "%d", &ret); } ClearNameValueList(&pdata); return ret; } /* UPNP_GetSpecificPortMappingEntry retrieves an existing port mapping * the result is returned in the intClient and intPort strings * please provide 16 and 6 bytes of data */ MINIUPNP_LIBSPEC int UPNP_GetSpecificPortMappingEntry(const char * controlURL, const char * servicetype, const char * extPort, const char * proto, const char * remoteHost, char * intClient, char * intPort, char * desc, char * enabled, char * leaseDuration) { struct NameValueParserData pdata; struct UPNParg * GetPortMappingArgs; char * buffer; int bufsize; char * p; int ret = UPNPCOMMAND_UNKNOWN_ERROR; if(!intPort || !intClient || !extPort || !proto) return UPNPCOMMAND_INVALID_ARGS; GetPortMappingArgs = calloc(4, sizeof(struct UPNParg)); if(GetPortMappingArgs == NULL) return UPNPCOMMAND_MEM_ALLOC_ERROR; GetPortMappingArgs[0].elt = "NewRemoteHost"; GetPortMappingArgs[0].val = remoteHost; GetPortMappingArgs[1].elt = "NewExternalPort"; GetPortMappingArgs[1].val = extPort; GetPortMappingArgs[2].elt = "NewProtocol"; GetPortMappingArgs[2].val = proto; buffer = simpleUPnPcommand(-1, controlURL, servicetype, "GetSpecificPortMappingEntry", GetPortMappingArgs, &bufsize); free(GetPortMappingArgs); if(!buffer) { return UPNPCOMMAND_HTTP_ERROR; } /*DisplayNameValueList(buffer, bufsize);*/ ParseNameValue(buffer, bufsize, &pdata); free(buffer); p = GetValueFromNameValueList(&pdata, "NewInternalClient"); if(p) { strncpy(intClient, p, 16); intClient[15] = '\0'; ret = UPNPCOMMAND_SUCCESS; } else intClient[0] = '\0'; p = GetValueFromNameValueList(&pdata, "NewInternalPort"); if(p) { strncpy(intPort, p, 6); intPort[5] = '\0'; } else intPort[0] = '\0'; p = GetValueFromNameValueList(&pdata, "NewEnabled"); if(p && enabled) { strncpy(enabled, p, 4); enabled[3] = '\0'; } p = GetValueFromNameValueList(&pdata, "NewPortMappingDescription"); if(p && desc) { strncpy(desc, p, 80); desc[79] = '\0'; } p = GetValueFromNameValueList(&pdata, "NewLeaseDuration"); if(p && leaseDuration) { strncpy(leaseDuration, p, 16); leaseDuration[15] = '\0'; } p = GetValueFromNameValueList(&pdata, "errorCode"); if(p) { ret = UPNPCOMMAND_UNKNOWN_ERROR; sscanf(p, "%d", &ret); } ClearNameValueList(&pdata); return ret; } /* UPNP_GetListOfPortMappings() * * Possible UPNP Error codes : * 606 Action not Authorized * 730 PortMappingNotFound - no port mapping is found in the specified range. * 733 InconsistantParameters - NewStartPort and NewEndPort values are not * consistent. */ MINIUPNP_LIBSPEC int UPNP_GetListOfPortMappings(const char * controlURL, const char * servicetype, const char * startPort, const char * endPort, const char * protocol, const char * numberOfPorts, struct PortMappingParserData * data) { struct NameValueParserData pdata; struct UPNParg * GetListOfPortMappingsArgs; const char * p; char * buffer; int bufsize; int ret = UPNPCOMMAND_UNKNOWN_ERROR; if(!startPort || !endPort || !protocol) return UPNPCOMMAND_INVALID_ARGS; GetListOfPortMappingsArgs = calloc(6, sizeof(struct UPNParg)); if(GetListOfPortMappingsArgs == NULL) return UPNPCOMMAND_MEM_ALLOC_ERROR; GetListOfPortMappingsArgs[0].elt = "NewStartPort"; GetListOfPortMappingsArgs[0].val = startPort; GetListOfPortMappingsArgs[1].elt = "NewEndPort"; GetListOfPortMappingsArgs[1].val = endPort; GetListOfPortMappingsArgs[2].elt = "NewProtocol"; GetListOfPortMappingsArgs[2].val = protocol; GetListOfPortMappingsArgs[3].elt = "NewManage"; GetListOfPortMappingsArgs[3].val = "1"; GetListOfPortMappingsArgs[4].elt = "NewNumberOfPorts"; GetListOfPortMappingsArgs[4].val = numberOfPorts?numberOfPorts:"1000"; buffer = simpleUPnPcommand(-1, controlURL, servicetype, "GetListOfPortMappings", GetListOfPortMappingsArgs, &bufsize); free(GetListOfPortMappingsArgs); if(!buffer) { return UPNPCOMMAND_HTTP_ERROR; } /*DisplayNameValueList(buffer, bufsize);*/ ParseNameValue(buffer, bufsize, &pdata); free(buffer); /*p = GetValueFromNameValueList(&pdata, "NewPortListing");*/ /*if(p) { printf("NewPortListing : %s\n", p); }*/ /*printf("NewPortListing(%d chars) : %s\n", pdata.portListingLength, pdata.portListing);*/ if(pdata.portListing) { /*struct PortMapping * pm; int i = 0;*/ ParsePortListing(pdata.portListing, pdata.portListingLength, data); ret = UPNPCOMMAND_SUCCESS; /* for(pm = data->head.lh_first; pm != NULL; pm = pm->entries.le_next) { printf("%2d %s %5hu->%s:%-5hu '%s' '%s'\n", i, pm->protocol, pm->externalPort, pm->internalClient, pm->internalPort, pm->description, pm->remoteHost); i++; } */ /*FreePortListing(&data);*/ } p = GetValueFromNameValueList(&pdata, "errorCode"); if(p) { ret = UPNPCOMMAND_UNKNOWN_ERROR; sscanf(p, "%d", &ret); } ClearNameValueList(&pdata); /*printf("%.*s", bufsize, buffer);*/ return ret; } /* IGD:2, functions for service WANIPv6FirewallControl:1 */ MINIUPNP_LIBSPEC int UPNP_GetFirewallStatus(const char * controlURL, const char * servicetype, int * firewallEnabled, int * inboundPinholeAllowed) { struct NameValueParserData pdata; char * buffer; int bufsize; char * fe, *ipa, *p; int ret = UPNPCOMMAND_UNKNOWN_ERROR; if(!firewallEnabled || !inboundPinholeAllowed) return UPNPCOMMAND_INVALID_ARGS; buffer = simpleUPnPcommand(-1, controlURL, servicetype, "GetFirewallStatus", 0, &bufsize); if(!buffer) { return UPNPCOMMAND_HTTP_ERROR; } ParseNameValue(buffer, bufsize, &pdata); free(buffer); fe = GetValueFromNameValueList(&pdata, "FirewallEnabled"); ipa = GetValueFromNameValueList(&pdata, "InboundPinholeAllowed"); if(ipa && fe) ret = UPNPCOMMAND_SUCCESS; if(fe) *firewallEnabled = my_atoui(fe); /*else *firewallEnabled = 0;*/ if(ipa) *inboundPinholeAllowed = my_atoui(ipa); /*else *inboundPinholeAllowed = 0;*/ p = GetValueFromNameValueList(&pdata, "errorCode"); if(p) { ret = UPNPCOMMAND_UNKNOWN_ERROR; sscanf(p, "%d", &ret); } ClearNameValueList(&pdata); return ret; } MINIUPNP_LIBSPEC int UPNP_GetOutboundPinholeTimeout(const char * controlURL, const char * servicetype, const char * remoteHost, const char * remotePort, const char * intClient, const char * intPort, const char * proto, int * opTimeout) { struct UPNParg * GetOutboundPinholeTimeoutArgs; char * buffer; int bufsize; struct NameValueParserData pdata; const char * resVal; int ret; if(!intPort || !intClient || !proto || !remotePort || !remoteHost) return UPNPCOMMAND_INVALID_ARGS; GetOutboundPinholeTimeoutArgs = calloc(6, sizeof(struct UPNParg)); if(GetOutboundPinholeTimeoutArgs == NULL) return UPNPCOMMAND_MEM_ALLOC_ERROR; GetOutboundPinholeTimeoutArgs[0].elt = "RemoteHost"; GetOutboundPinholeTimeoutArgs[0].val = remoteHost; GetOutboundPinholeTimeoutArgs[1].elt = "RemotePort"; GetOutboundPinholeTimeoutArgs[1].val = remotePort; GetOutboundPinholeTimeoutArgs[2].elt = "Protocol"; GetOutboundPinholeTimeoutArgs[2].val = proto; GetOutboundPinholeTimeoutArgs[3].elt = "InternalPort"; GetOutboundPinholeTimeoutArgs[3].val = intPort; GetOutboundPinholeTimeoutArgs[4].elt = "InternalClient"; GetOutboundPinholeTimeoutArgs[4].val = intClient; buffer = simpleUPnPcommand(-1, controlURL, servicetype, "GetOutboundPinholeTimeout", GetOutboundPinholeTimeoutArgs, &bufsize); free(GetOutboundPinholeTimeoutArgs); if(!buffer) return UPNPCOMMAND_HTTP_ERROR; ParseNameValue(buffer, bufsize, &pdata); free(buffer); resVal = GetValueFromNameValueList(&pdata, "errorCode"); if(resVal) { ret = UPNPCOMMAND_UNKNOWN_ERROR; sscanf(resVal, "%d", &ret); } else { const char * p = GetValueFromNameValueList(&pdata, "OutboundPinholeTimeout"); if(p) *opTimeout = my_atoui(p); ret = UPNPCOMMAND_SUCCESS; } ClearNameValueList(&pdata); return ret; } MINIUPNP_LIBSPEC int UPNP_AddPinhole(const char * controlURL, const char * servicetype, const char * remoteHost, const char * remotePort, const char * intClient, const char * intPort, const char * proto, const char * leaseTime, char * uniqueID) { struct UPNParg * AddPinholeArgs; char * buffer; int bufsize; struct NameValueParserData pdata; const char * resVal; char * p; int ret; if(!intPort || !intClient || !proto || !remoteHost || !remotePort || !leaseTime) return UPNPCOMMAND_INVALID_ARGS; AddPinholeArgs = calloc(7, sizeof(struct UPNParg)); if(AddPinholeArgs == NULL) return UPNPCOMMAND_MEM_ALLOC_ERROR; /* RemoteHost can be wilcarded */ if(strncmp(remoteHost, "empty", 5)==0) { AddPinholeArgs[0].elt = "RemoteHost"; AddPinholeArgs[0].val = ""; } else { AddPinholeArgs[0].elt = "RemoteHost"; AddPinholeArgs[0].val = remoteHost; } AddPinholeArgs[1].elt = "RemotePort"; AddPinholeArgs[1].val = remotePort; AddPinholeArgs[2].elt = "Protocol"; AddPinholeArgs[2].val = proto; AddPinholeArgs[3].elt = "InternalPort"; AddPinholeArgs[3].val = intPort; if(strncmp(intClient, "empty", 5)==0) { AddPinholeArgs[4].elt = "InternalClient"; AddPinholeArgs[4].val = ""; } else { AddPinholeArgs[4].elt = "InternalClient"; AddPinholeArgs[4].val = intClient; } AddPinholeArgs[5].elt = "LeaseTime"; AddPinholeArgs[5].val = leaseTime; buffer = simpleUPnPcommand(-1, controlURL, servicetype, "AddPinhole", AddPinholeArgs, &bufsize); free(AddPinholeArgs); if(!buffer) return UPNPCOMMAND_HTTP_ERROR; ParseNameValue(buffer, bufsize, &pdata); free(buffer); p = GetValueFromNameValueList(&pdata, "UniqueID"); if(p) { strncpy(uniqueID, p, 8); uniqueID[7] = '\0'; } resVal = GetValueFromNameValueList(&pdata, "errorCode"); if(resVal) { /*printf("AddPortMapping errorCode = '%s'\n", resVal);*/ ret = UPNPCOMMAND_UNKNOWN_ERROR; sscanf(resVal, "%d", &ret); } else { ret = UPNPCOMMAND_SUCCESS; } ClearNameValueList(&pdata); return ret; } MINIUPNP_LIBSPEC int UPNP_UpdatePinhole(const char * controlURL, const char * servicetype, const char * uniqueID, const char * leaseTime) { struct UPNParg * UpdatePinholeArgs; char * buffer; int bufsize; struct NameValueParserData pdata; const char * resVal; int ret; if(!uniqueID || !leaseTime) return UPNPCOMMAND_INVALID_ARGS; UpdatePinholeArgs = calloc(3, sizeof(struct UPNParg)); if(UpdatePinholeArgs == NULL) return UPNPCOMMAND_MEM_ALLOC_ERROR; UpdatePinholeArgs[0].elt = "UniqueID"; UpdatePinholeArgs[0].val = uniqueID; UpdatePinholeArgs[1].elt = "NewLeaseTime"; UpdatePinholeArgs[1].val = leaseTime; buffer = simpleUPnPcommand(-1, controlURL, servicetype, "UpdatePinhole", UpdatePinholeArgs, &bufsize); free(UpdatePinholeArgs); if(!buffer) return UPNPCOMMAND_HTTP_ERROR; ParseNameValue(buffer, bufsize, &pdata); free(buffer); resVal = GetValueFromNameValueList(&pdata, "errorCode"); if(resVal) { /*printf("AddPortMapping errorCode = '%s'\n", resVal); */ ret = UPNPCOMMAND_UNKNOWN_ERROR; sscanf(resVal, "%d", &ret); } else { ret = UPNPCOMMAND_SUCCESS; } ClearNameValueList(&pdata); return ret; } MINIUPNP_LIBSPEC int UPNP_DeletePinhole(const char * controlURL, const char * servicetype, const char * uniqueID) { /*struct NameValueParserData pdata;*/ struct UPNParg * DeletePinholeArgs; char * buffer; int bufsize; struct NameValueParserData pdata; const char * resVal; int ret; if(!uniqueID) return UPNPCOMMAND_INVALID_ARGS; DeletePinholeArgs = calloc(2, sizeof(struct UPNParg)); if(DeletePinholeArgs == NULL) return UPNPCOMMAND_MEM_ALLOC_ERROR; DeletePinholeArgs[0].elt = "UniqueID"; DeletePinholeArgs[0].val = uniqueID; buffer = simpleUPnPcommand(-1, controlURL, servicetype, "DeletePinhole", DeletePinholeArgs, &bufsize); free(DeletePinholeArgs); if(!buffer) return UPNPCOMMAND_HTTP_ERROR; /*DisplayNameValueList(buffer, bufsize);*/ ParseNameValue(buffer, bufsize, &pdata); free(buffer); resVal = GetValueFromNameValueList(&pdata, "errorCode"); if(resVal) { ret = UPNPCOMMAND_UNKNOWN_ERROR; sscanf(resVal, "%d", &ret); } else { ret = UPNPCOMMAND_SUCCESS; } ClearNameValueList(&pdata); return ret; } MINIUPNP_LIBSPEC int UPNP_CheckPinholeWorking(const char * controlURL, const char * servicetype, const char * uniqueID, int * isWorking) { struct NameValueParserData pdata; struct UPNParg * CheckPinholeWorkingArgs; char * buffer; int bufsize; char * p; int ret = UPNPCOMMAND_UNKNOWN_ERROR; if(!uniqueID) return UPNPCOMMAND_INVALID_ARGS; CheckPinholeWorkingArgs = calloc(4, sizeof(struct UPNParg)); if(CheckPinholeWorkingArgs == NULL) return UPNPCOMMAND_MEM_ALLOC_ERROR; CheckPinholeWorkingArgs[0].elt = "UniqueID"; CheckPinholeWorkingArgs[0].val = uniqueID; buffer = simpleUPnPcommand(-1, controlURL, servicetype, "CheckPinholeWorking", CheckPinholeWorkingArgs, &bufsize); free(CheckPinholeWorkingArgs); if(!buffer) { return UPNPCOMMAND_HTTP_ERROR; } ParseNameValue(buffer, bufsize, &pdata); free(buffer); p = GetValueFromNameValueList(&pdata, "IsWorking"); if(p) { *isWorking=my_atoui(p); ret = UPNPCOMMAND_SUCCESS; } else *isWorking = 0; p = GetValueFromNameValueList(&pdata, "errorCode"); if(p) { ret = UPNPCOMMAND_UNKNOWN_ERROR; sscanf(p, "%d", &ret); } ClearNameValueList(&pdata); return ret; } MINIUPNP_LIBSPEC int UPNP_GetPinholePackets(const char * controlURL, const char * servicetype, const char * uniqueID, int * packets) { struct NameValueParserData pdata; struct UPNParg * GetPinholePacketsArgs; char * buffer; int bufsize; char * p; int ret = UPNPCOMMAND_UNKNOWN_ERROR; if(!uniqueID) return UPNPCOMMAND_INVALID_ARGS; GetPinholePacketsArgs = calloc(4, sizeof(struct UPNParg)); if(GetPinholePacketsArgs == NULL) return UPNPCOMMAND_MEM_ALLOC_ERROR; GetPinholePacketsArgs[0].elt = "UniqueID"; GetPinholePacketsArgs[0].val = uniqueID; buffer = simpleUPnPcommand(-1, controlURL, servicetype, "GetPinholePackets", GetPinholePacketsArgs, &bufsize); free(GetPinholePacketsArgs); if(!buffer) return UPNPCOMMAND_HTTP_ERROR; ParseNameValue(buffer, bufsize, &pdata); free(buffer); p = GetValueFromNameValueList(&pdata, "PinholePackets"); if(p) { *packets=my_atoui(p); ret = UPNPCOMMAND_SUCCESS; } p = GetValueFromNameValueList(&pdata, "errorCode"); if(p) { ret = UPNPCOMMAND_UNKNOWN_ERROR; sscanf(p, "%d", &ret); } ClearNameValueList(&pdata); return ret; } opengnb-ver1.6.0.a/libs/miniupnpc/upnpcommands.h000066400000000000000000000324161500454252100217160ustar00rootroot00000000000000/* $Id: upnpcommands.h,v 1.33 2019/02/10 12:29:25 nanard Exp $ */ /* Miniupnp project : http://miniupnp.free.fr/ * Author : Thomas Bernard * Copyright (c) 2005-2018 Thomas Bernard * This software is subject to the conditions detailed in the * LICENCE file provided within this distribution */ #ifndef UPNPCOMMANDS_H_INCLUDED #define UPNPCOMMANDS_H_INCLUDED #include "miniupnpc_declspec.h" #include "miniupnpctypes.h" /* MiniUPnPc return codes : */ #define UPNPCOMMAND_SUCCESS (0) #define UPNPCOMMAND_UNKNOWN_ERROR (-1) #define UPNPCOMMAND_INVALID_ARGS (-2) #define UPNPCOMMAND_HTTP_ERROR (-3) #define UPNPCOMMAND_INVALID_RESPONSE (-4) #define UPNPCOMMAND_MEM_ALLOC_ERROR (-5) #ifdef __cplusplus extern "C" { #endif struct PortMappingParserData; MINIUPNP_LIBSPEC UNSIGNED_INTEGER UPNP_GetTotalBytesSent(const char * controlURL, const char * servicetype); MINIUPNP_LIBSPEC UNSIGNED_INTEGER UPNP_GetTotalBytesReceived(const char * controlURL, const char * servicetype); MINIUPNP_LIBSPEC UNSIGNED_INTEGER UPNP_GetTotalPacketsSent(const char * controlURL, const char * servicetype); MINIUPNP_LIBSPEC UNSIGNED_INTEGER UPNP_GetTotalPacketsReceived(const char * controlURL, const char * servicetype); /* UPNP_GetStatusInfo() * status and lastconnerror are 64 byte buffers * Return values : * UPNPCOMMAND_SUCCESS, UPNPCOMMAND_INVALID_ARGS, UPNPCOMMAND_UNKNOWN_ERROR * or a UPnP Error code */ MINIUPNP_LIBSPEC int UPNP_GetStatusInfo(const char * controlURL, const char * servicetype, char * status, unsigned int * uptime, char * lastconnerror); /* UPNP_GetConnectionTypeInfo() * argument connectionType is a 64 character buffer * Return Values : * UPNPCOMMAND_SUCCESS, UPNPCOMMAND_INVALID_ARGS, UPNPCOMMAND_UNKNOWN_ERROR * or a UPnP Error code */ MINIUPNP_LIBSPEC int UPNP_GetConnectionTypeInfo(const char * controlURL, const char * servicetype, char * connectionType); /* UPNP_GetExternalIPAddress() call the corresponding UPNP method. * if the third arg is not null the value is copied to it. * at least 16 bytes must be available * * Return values : * 0 : SUCCESS * NON ZERO : ERROR Either an UPnP error code or an unknown error. * * possible UPnP Errors : * 402 Invalid Args - See UPnP Device Architecture section on Control. * 501 Action Failed - See UPnP Device Architecture section on Control. */ MINIUPNP_LIBSPEC int UPNP_GetExternalIPAddress(const char * controlURL, const char * servicetype, char * extIpAdd); /* UPNP_GetLinkLayerMaxBitRates() * call WANCommonInterfaceConfig:1#GetCommonLinkProperties * * return values : * UPNPCOMMAND_SUCCESS, UPNPCOMMAND_INVALID_ARGS, UPNPCOMMAND_UNKNOWN_ERROR * or a UPnP Error Code. */ MINIUPNP_LIBSPEC int UPNP_GetLinkLayerMaxBitRates(const char* controlURL, const char* servicetype, unsigned int * bitrateDown, unsigned int * bitrateUp); /* UPNP_AddPortMapping() * if desc is NULL, it will be defaulted to "libminiupnpc" * remoteHost is usually NULL because IGD don't support it. * * Return values : * 0 : SUCCESS * NON ZERO : ERROR. Either an UPnP error code or an unknown error. * * List of possible UPnP errors for AddPortMapping : * errorCode errorDescription (short) - Description (long) * 402 Invalid Args - See UPnP Device Architecture section on Control. * 501 Action Failed - See UPnP Device Architecture section on Control. * 606 Action not authorized - The action requested REQUIRES authorization and * the sender was not authorized. * 715 WildCardNotPermittedInSrcIP - The source IP address cannot be * wild-carded * 716 WildCardNotPermittedInExtPort - The external port cannot be wild-carded * 718 ConflictInMappingEntry - The port mapping entry specified conflicts * with a mapping assigned previously to another client * 724 SamePortValuesRequired - Internal and External port values * must be the same * 725 OnlyPermanentLeasesSupported - The NAT implementation only supports * permanent lease times on port mappings * 726 RemoteHostOnlySupportsWildcard - RemoteHost must be a wildcard * and cannot be a specific IP address or DNS name * 727 ExternalPortOnlySupportsWildcard - ExternalPort must be a wildcard and * cannot be a specific port value * 728 NoPortMapsAvailable - There are not enough free ports available to * complete port mapping. * 729 ConflictWithOtherMechanisms - Attempted port mapping is not allowed * due to conflict with other mechanisms. * 732 WildCardNotPermittedInIntPort - The internal port cannot be wild-carded */ MINIUPNP_LIBSPEC int UPNP_AddPortMapping(const char * controlURL, const char * servicetype, const char * extPort, const char * inPort, const char * inClient, const char * desc, const char * proto, const char * remoteHost, const char * leaseDuration); /* UPNP_AddAnyPortMapping() * if desc is NULL, it will be defaulted to "libminiupnpc" * remoteHost is usually NULL because IGD don't support it. * * Return values : * 0 : SUCCESS * NON ZERO : ERROR. Either an UPnP error code or an unknown error. * * List of possible UPnP errors for AddPortMapping : * errorCode errorDescription (short) - Description (long) * 402 Invalid Args - See UPnP Device Architecture section on Control. * 501 Action Failed - See UPnP Device Architecture section on Control. * 606 Action not authorized - The action requested REQUIRES authorization and * the sender was not authorized. * 715 WildCardNotPermittedInSrcIP - The source IP address cannot be * wild-carded * 716 WildCardNotPermittedInExtPort - The external port cannot be wild-carded * 728 NoPortMapsAvailable - There are not enough free ports available to * complete port mapping. * 729 ConflictWithOtherMechanisms - Attempted port mapping is not allowed * due to conflict with other mechanisms. * 732 WildCardNotPermittedInIntPort - The internal port cannot be wild-carded */ MINIUPNP_LIBSPEC int UPNP_AddAnyPortMapping(const char * controlURL, const char * servicetype, const char * extPort, const char * inPort, const char * inClient, const char * desc, const char * proto, const char * remoteHost, const char * leaseDuration, char * reservedPort); /* UPNP_DeletePortMapping() * Use same argument values as what was used for AddPortMapping(). * remoteHost is usually NULL because IGD don't support it. * Return Values : * 0 : SUCCESS * NON ZERO : error. Either an UPnP error code or an undefined error. * * List of possible UPnP errors for DeletePortMapping : * 402 Invalid Args - See UPnP Device Architecture section on Control. * 606 Action not authorized - The action requested REQUIRES authorization * and the sender was not authorized. * 714 NoSuchEntryInArray - The specified value does not exist in the array */ MINIUPNP_LIBSPEC int UPNP_DeletePortMapping(const char * controlURL, const char * servicetype, const char * extPort, const char * proto, const char * remoteHost); /* UPNP_DeletePortRangeMapping() * Use same argument values as what was used for AddPortMapping(). * remoteHost is usually NULL because IGD don't support it. * Return Values : * 0 : SUCCESS * NON ZERO : error. Either an UPnP error code or an undefined error. * * List of possible UPnP errors for DeletePortMapping : * 606 Action not authorized - The action requested REQUIRES authorization * and the sender was not authorized. * 730 PortMappingNotFound - This error message is returned if no port * mapping is found in the specified range. * 733 InconsistentParameters - NewStartPort and NewEndPort values are not consistent. */ MINIUPNP_LIBSPEC int UPNP_DeletePortMappingRange(const char * controlURL, const char * servicetype, const char * extPortStart, const char * extPortEnd, const char * proto, const char * manage); /* UPNP_GetPortMappingNumberOfEntries() * not supported by all routers */ MINIUPNP_LIBSPEC int UPNP_GetPortMappingNumberOfEntries(const char * controlURL, const char * servicetype, unsigned int * numEntries); /* UPNP_GetSpecificPortMappingEntry() * retrieves an existing port mapping * params : * in extPort * in proto * in remoteHost * out intClient (16 bytes) * out intPort (6 bytes) * out desc (80 bytes) * out enabled (4 bytes) * out leaseDuration (16 bytes) * * return value : * UPNPCOMMAND_SUCCESS, UPNPCOMMAND_INVALID_ARGS, UPNPCOMMAND_UNKNOWN_ERROR * or a UPnP Error Code. * * List of possible UPnP errors for _GetSpecificPortMappingEntry : * 402 Invalid Args - See UPnP Device Architecture section on Control. * 501 Action Failed - See UPnP Device Architecture section on Control. * 606 Action not authorized - The action requested REQUIRES authorization * and the sender was not authorized. * 714 NoSuchEntryInArray - The specified value does not exist in the array. */ MINIUPNP_LIBSPEC int UPNP_GetSpecificPortMappingEntry(const char * controlURL, const char * servicetype, const char * extPort, const char * proto, const char * remoteHost, char * intClient, char * intPort, char * desc, char * enabled, char * leaseDuration); /* UPNP_GetGenericPortMappingEntry() * params : * in index * out extPort (6 bytes) * out intClient (16 bytes) * out intPort (6 bytes) * out protocol (4 bytes) * out desc (80 bytes) * out enabled (4 bytes) * out rHost (64 bytes) * out duration (16 bytes) * * return value : * UPNPCOMMAND_SUCCESS, UPNPCOMMAND_INVALID_ARGS, UPNPCOMMAND_UNKNOWN_ERROR * or a UPnP Error Code. * * Possible UPNP Error codes : * 402 Invalid Args - See UPnP Device Architecture section on Control. * 606 Action not authorized - The action requested REQUIRES authorization * and the sender was not authorized. * 713 SpecifiedArrayIndexInvalid - The specified array index is out of bounds */ MINIUPNP_LIBSPEC int UPNP_GetGenericPortMappingEntry(const char * controlURL, const char * servicetype, const char * index, char * extPort, char * intClient, char * intPort, char * protocol, char * desc, char * enabled, char * rHost, char * duration); /* UPNP_GetListOfPortMappings() Available in IGD v2 * * * Possible UPNP Error codes : * 606 Action not Authorized * 730 PortMappingNotFound - no port mapping is found in the specified range. * 733 InconsistantParameters - NewStartPort and NewEndPort values are not * consistent. */ MINIUPNP_LIBSPEC int UPNP_GetListOfPortMappings(const char * controlURL, const char * servicetype, const char * startPort, const char * endPort, const char * protocol, const char * numberOfPorts, struct PortMappingParserData * data); /* IGD:2, functions for service WANIPv6FirewallControl:1 */ MINIUPNP_LIBSPEC int UPNP_GetFirewallStatus(const char * controlURL, const char * servicetype, int * firewallEnabled, int * inboundPinholeAllowed); MINIUPNP_LIBSPEC int UPNP_GetOutboundPinholeTimeout(const char * controlURL, const char * servicetype, const char * remoteHost, const char * remotePort, const char * intClient, const char * intPort, const char * proto, int * opTimeout); MINIUPNP_LIBSPEC int UPNP_AddPinhole(const char * controlURL, const char * servicetype, const char * remoteHost, const char * remotePort, const char * intClient, const char * intPort, const char * proto, const char * leaseTime, char * uniqueID); MINIUPNP_LIBSPEC int UPNP_UpdatePinhole(const char * controlURL, const char * servicetype, const char * uniqueID, const char * leaseTime); MINIUPNP_LIBSPEC int UPNP_DeletePinhole(const char * controlURL, const char * servicetype, const char * uniqueID); MINIUPNP_LIBSPEC int UPNP_CheckPinholeWorking(const char * controlURL, const char * servicetype, const char * uniqueID, int * isWorking); MINIUPNP_LIBSPEC int UPNP_GetPinholePackets(const char * controlURL, const char * servicetype, const char * uniqueID, int * packets); #ifdef __cplusplus } #endif #endif opengnb-ver1.6.0.a/libs/miniupnpc/upnpdev.c000066400000000000000000000010711500454252100206570ustar00rootroot00000000000000/* $Id: upnpdev.c,v 1.1 2015/08/28 12:14:19 nanard Exp $ */ /* Project : miniupnp * Web : http://miniupnp.free.fr/ * Author : Thomas BERNARD * copyright (c) 2005-2015 Thomas Bernard * This software is subjet to the conditions detailed in the * provided LICENSE file. */ #include #include "upnpdev.h" /* freeUPNPDevlist() should be used to * free the chained list returned by upnpDiscover() */ void freeUPNPDevlist(struct UPNPDev * devlist) { struct UPNPDev * next; while(devlist) { next = devlist->pNext; free(devlist); devlist = next; } } opengnb-ver1.6.0.a/libs/miniupnpc/upnpdev.h000066400000000000000000000013251500454252100206660ustar00rootroot00000000000000/* $Id: upnpdev.h,v 1.2 2018/04/06 10:53:15 nanard Exp $ */ /* Project : miniupnp * Web : http://miniupnp.free.fr/ * Author : Thomas BERNARD * copyright (c) 2005-2018 Thomas Bernard * This software is subjet to the conditions detailed in the * provided LICENSE file. */ #ifndef UPNPDEV_H_INCLUDED #define UPNPDEV_H_INCLUDED #include "miniupnpc_declspec.h" #ifdef __cplusplus extern "C" { #endif struct UPNPDev { struct UPNPDev * pNext; char * descURL; char * st; char * usn; unsigned int scope_id; char buffer[3]; }; /* freeUPNPDevlist() * free list returned by upnpDiscover() */ MINIUPNP_LIBSPEC void freeUPNPDevlist(struct UPNPDev * devlist); #ifdef __cplusplus } #endif #endif /* UPNPDEV_H_INCLUDED */ opengnb-ver1.6.0.a/libs/miniupnpc/upnperrors.c000066400000000000000000000043631500454252100214240ustar00rootroot00000000000000/* $Id: upnperrors.c,v 1.10 2019/08/24 08:49:53 nanard Exp $ */ /* vim: tabstop=4 shiftwidth=4 noexpandtab * Project : miniupnp * Author : Thomas BERNARD * copyright (c) 2007-2019 Thomas Bernard * All Right reserved. * http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/ * This software is subjet to the conditions detailed in the * provided LICENCE file. */ #include #include "upnperrors.h" #include "upnpcommands.h" #include "miniupnpc.h" const char * strupnperror(int err) { const char * s = NULL; switch(err) { case UPNPCOMMAND_SUCCESS: s = "Success"; break; case UPNPCOMMAND_UNKNOWN_ERROR: s = "Miniupnpc Unknown Error"; break; case UPNPCOMMAND_INVALID_ARGS: s = "Miniupnpc Invalid Arguments"; break; case UPNPCOMMAND_INVALID_RESPONSE: s = "Miniupnpc Invalid response"; break; case UPNPCOMMAND_HTTP_ERROR: s = "Miniupnpc HTTP error"; break; case UPNPDISCOVER_SOCKET_ERROR: s = "Miniupnpc Socket error"; break; case UPNPDISCOVER_MEMORY_ERROR: case UPNPCOMMAND_MEM_ALLOC_ERROR: s = "Miniupnpc Memory allocation error"; break; case 401: s = "Invalid Action"; break; case 402: s = "Invalid Args"; break; case 501: s = "Action Failed"; break; case 606: s = "Action not authorized"; break; case 701: s = "PinholeSpaceExhausted"; break; case 702: s = "FirewallDisabled"; break; case 703: s = "InboundPinholeNotAllowed"; break; case 704: s = "NoSuchEntry"; break; case 705: s = "ProtocolNotSupported"; break; case 706: s = "InternalPortWildcardingNotAllowed"; break; case 707: s = "ProtocolWildcardingNotAllowed"; break; case 708: s = "InvalidLayer2Address"; break; case 709: s = "NoPacketSent"; break; case 713: s = "SpecifiedArrayIndexInvalid"; break; case 714: s = "NoSuchEntryInArray"; break; case 715: s = "WildCardNotPermittedInSrcIP"; break; case 716: s = "WildCardNotPermittedInExtPort"; break; case 718: s = "ConflictInMappingEntry"; break; case 724: s = "SamePortValuesRequired"; break; case 725: s = "OnlyPermanentLeasesSupported"; break; case 726: s = "RemoteHostOnlySupportsWildcard"; break; case 727: s = "ExternalPortOnlySupportsWildcard"; break; default: s = "UnknownError"; break; } return s; } opengnb-ver1.6.0.a/libs/miniupnpc/upnperrors.h000066400000000000000000000011601500454252100214210ustar00rootroot00000000000000/* $Id: upnperrors.h,v 1.6 2015/07/21 13:16:55 nanard Exp $ */ /* (c) 2007-2015 Thomas Bernard * All rights reserved. * MiniUPnP Project. * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ * This software is subjet to the conditions detailed in the * provided LICENCE file. */ #ifndef UPNPERRORS_H_INCLUDED #define UPNPERRORS_H_INCLUDED #include "miniupnpc_declspec.h" #ifdef __cplusplus extern "C" { #endif /* strupnperror() * Return a string description of the UPnP error code * or NULL for undefinded errors */ MINIUPNP_LIBSPEC const char * strupnperror(int err); #ifdef __cplusplus } #endif #endif opengnb-ver1.6.0.a/libs/miniupnpc/upnpreplyparse.c000066400000000000000000000106551500454252100222770ustar00rootroot00000000000000/* $Id: upnpreplyparse.c,v 1.21 2019/04/08 13:30:51 nanard Exp $ */ /* vim: tabstop=4 shiftwidth=4 noexpandtab * MiniUPnP project * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ * (c) 2006-2019 Thomas Bernard * This software is subject to the conditions detailed * in the LICENCE file provided within the distribution */ #include #include #include #include "upnpreplyparse.h" #include "minixml.h" static void NameValueParserStartElt(void * d, const char * name, int l) { struct NameValueParserData * data = (struct NameValueParserData *)d; data->topelt = 1; if(l>63) l = 63; memcpy(data->curelt, name, l); data->curelt[l] = '\0'; data->cdata = NULL; data->cdatalen = 0; } static void NameValueParserEndElt(void * d, const char * name, int namelen) { struct NameValueParserData * data = (struct NameValueParserData *)d; struct NameValue * nv; (void)name; (void)namelen; if(!data->topelt) return; if(strcmp(data->curelt, "NewPortListing") != 0) { int l; /* standard case. Limited to n chars strings */ l = data->cdatalen; nv = malloc(sizeof(struct NameValue)); if(nv == NULL) { /* malloc error */ #ifdef DEBUG fprintf(stderr, "%s: error allocating memory", "NameValueParserEndElt"); #endif /* DEBUG */ return; } if(l>=(int)sizeof(nv->value)) l = sizeof(nv->value) - 1; strncpy(nv->name, data->curelt, 64); nv->name[63] = '\0'; if(data->cdata != NULL) { memcpy(nv->value, data->cdata, l); nv->value[l] = '\0'; } else { nv->value[0] = '\0'; } nv->l_next = data->l_head; /* insert in list */ data->l_head = nv; } data->cdata = NULL; data->cdatalen = 0; data->topelt = 0; } static void NameValueParserGetData(void * d, const char * datas, int l) { struct NameValueParserData * data = (struct NameValueParserData *)d; if(strcmp(data->curelt, "NewPortListing") == 0) { /* specific case for NewPortListing which is a XML Document */ free(data->portListing); data->portListing = malloc(l + 1); if(!data->portListing) { /* malloc error */ #ifdef DEBUG fprintf(stderr, "%s: error allocating memory", "NameValueParserGetData"); #endif /* DEBUG */ return; } memcpy(data->portListing, datas, l); data->portListing[l] = '\0'; data->portListingLength = l; } else { /* standard case. */ data->cdata = datas; data->cdatalen = l; } } void ParseNameValue(const char * buffer, int bufsize, struct NameValueParserData * data) { struct xmlparser parser; memset(data, 0, sizeof(struct NameValueParserData)); /* init xmlparser object */ parser.xmlstart = buffer; parser.xmlsize = bufsize; parser.data = data; parser.starteltfunc = NameValueParserStartElt; parser.endeltfunc = NameValueParserEndElt; parser.datafunc = NameValueParserGetData; parser.attfunc = 0; parsexml(&parser); } void ClearNameValueList(struct NameValueParserData * pdata) { struct NameValue * nv; if(pdata->portListing) { free(pdata->portListing); pdata->portListing = NULL; pdata->portListingLength = 0; } while((nv = pdata->l_head) != NULL) { pdata->l_head = nv->l_next; free(nv); } } char * GetValueFromNameValueList(struct NameValueParserData * pdata, const char * Name) { struct NameValue * nv; char * p = NULL; for(nv = pdata->l_head; (nv != NULL) && (p == NULL); nv = nv->l_next) { if(strcmp(nv->name, Name) == 0) p = nv->value; } return p; } #if 0 /* useless now that minixml ignores namespaces by itself */ char * GetValueFromNameValueListIgnoreNS(struct NameValueParserData * pdata, const char * Name) { struct NameValue * nv; char * p = NULL; char * pname; for(nv = pdata->head.lh_first; (nv != NULL) && (p == NULL); nv = nv->entries.le_next) { pname = strrchr(nv->name, ':'); if(pname) pname++; else pname = nv->name; if(strcmp(pname, Name)==0) p = nv->value; } return p; } #endif /* debug all-in-one function * do parsing then display to stdout */ #ifdef DEBUG void DisplayNameValueList(char * buffer, int bufsize) { struct NameValueParserData pdata; struct NameValue * nv; ParseNameValue(buffer, bufsize, &pdata); for(nv = pdata.l_head; nv != NULL; nv = nv->l_next) { printf("%s = %s\n", nv->name, nv->value); } ClearNameValueList(&pdata); } #endif /* DEBUG */ opengnb-ver1.6.0.a/libs/miniupnpc/upnpreplyparse.h000066400000000000000000000025211500454252100222750ustar00rootroot00000000000000/* $Id: upnpreplyparse.h,v 1.19 2014/10/27 16:33:19 nanard Exp $ */ /* MiniUPnP project * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ * (c) 2006-2013 Thomas Bernard * This software is subject to the conditions detailed * in the LICENCE file provided within the distribution */ #ifndef UPNPREPLYPARSE_H_INCLUDED #define UPNPREPLYPARSE_H_INCLUDED #ifdef __cplusplus extern "C" { #endif struct NameValue { struct NameValue * l_next; char name[64]; char value[128]; }; struct NameValueParserData { struct NameValue * l_head; char curelt[64]; char * portListing; int portListingLength; int topelt; const char * cdata; int cdatalen; }; /* ParseNameValue() */ void ParseNameValue(const char * buffer, int bufsize, struct NameValueParserData * data); /* ClearNameValueList() */ void ClearNameValueList(struct NameValueParserData * pdata); /* GetValueFromNameValueList() */ char * GetValueFromNameValueList(struct NameValueParserData * pdata, const char * Name); #if 0 /* GetValueFromNameValueListIgnoreNS() */ char * GetValueFromNameValueListIgnoreNS(struct NameValueParserData * pdata, const char * Name); #endif /* DisplayNameValueList() */ #ifdef DEBUG void DisplayNameValueList(char * buffer, int bufsize); #endif #ifdef __cplusplus } #endif #endif opengnb-ver1.6.0.a/libs/protocol/000077500000000000000000000000001500454252100166725ustar00rootroot00000000000000opengnb-ver1.6.0.a/libs/protocol/network_protocol.h000066400000000000000000000041141500454252100224550ustar00rootroot00000000000000#ifndef NETWORK_PROTOCOL_H #define NETWORK_PROTOCOL_H #include #if defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) #include #include #include #include #include #include #include #include #include #endif #if defined(_WIN32) #include #endif #ifndef ETH_ALEN #define ETH_ALEN 6 #endif #ifndef ARPHRD_ETHER #define ARPHRD_ETHER 1 #endif #ifndef ETH_P_IP #define ETH_P_IP 0x0800 #endif #ifndef ETH_P_ARP #define ETH_P_ARP 0x0806 #endif #ifndef ETH_P_IPV6 #define ETH_P_IPV6 0x86DD #endif #ifndef ETH_P_8021Q #define ETH_P_8021Q 0x8100 #endif struct iphdr { #if __BYTE_ORDER__==__ORDER_LITTLE_ENDIAN__ u_char ihl:4, /* header length */ version:4; /* version */ #endif #if __BYTE_ORDER__==__ORDER_BIG_ENDIAN__ u_char version:4, /* version */ ihl:4; /* header length */ #endif u_char tos; /* type of service */ short tot_len; /* total length */ u_short id; /* identification */ short off; /* fragment offset field */ u_char ttl; /* time to live */ u_char protocol; /* protocol */ u_short check; /* checksum */ struct in_addr saddr; struct in_addr daddr; /* source and dest address */ }; #pragma pack(push, 1) struct gnb_in6_addr { union { uint8_t __u6_addr8[16]; uint16_t __u6_addr16[8]; uint32_t __u6_addr32[4]; } __in6_u; }__attribute__ ((__packed__)); struct ip6_hdr { union { struct ip6_hdrctl { uint32_t ip6_un1_flow; /* 20 bits of flow-ID */ uint16_t ip6_un1_plen; /* payload length */ uint8_t ip6_un1_nxt; /* next header */ uint8_t ip6_un1_hlim; /* hop limit */ } ip6_un1; uint8_t ip6_un2_vfc; /* 4 bits version, top 4 bits class */ } ip6_ctlun; struct gnb_in6_addr ip6_src; /* source address */ struct gnb_in6_addr ip6_dst; /* destination address */ } __attribute__ ((__packed__)); #pragma pack(pop) #endif opengnb-ver1.6.0.a/libs/tap-windows/000077500000000000000000000000001500454252100173055ustar00rootroot00000000000000opengnb-ver1.6.0.a/libs/tap-windows/tap-windows.h000066400000000000000000000062171500454252100217400ustar00rootroot00000000000000/* * TAP-Windows -- A kernel driver to provide virtual tap * device functionality on Windows. * * This code was inspired by the CIPE-Win32 driver by Damion K. Wilson. * * This source code is Copyright (C) 2002-2014 OpenVPN Technologies, Inc., * and is released under the GPL version 2 (see below). This particular file * (tap-windows.h) is also licensed using the MIT license (see COPYRIGHT.MIT). * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 * as published by the Free Software Foundation. * * 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 (see the file COPYING included with this * distribution); if not, write to the Free Software Foundation, Inc., * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef __TAP_WIN_H #define __TAP_WIN_H /* * ============= * TAP IOCTLs * ============= */ #define TAP_WIN_CONTROL_CODE(request,method) \ CTL_CODE (FILE_DEVICE_UNKNOWN, request, method, FILE_ANY_ACCESS) /* Present in 8.1 */ #define TAP_WIN_IOCTL_GET_MAC TAP_WIN_CONTROL_CODE (1, METHOD_BUFFERED) #define TAP_WIN_IOCTL_GET_VERSION TAP_WIN_CONTROL_CODE (2, METHOD_BUFFERED) #define TAP_WIN_IOCTL_GET_MTU TAP_WIN_CONTROL_CODE (3, METHOD_BUFFERED) #define TAP_WIN_IOCTL_GET_INFO TAP_WIN_CONTROL_CODE (4, METHOD_BUFFERED) #define TAP_WIN_IOCTL_CONFIG_POINT_TO_POINT TAP_WIN_CONTROL_CODE (5, METHOD_BUFFERED) #define TAP_WIN_IOCTL_SET_MEDIA_STATUS TAP_WIN_CONTROL_CODE (6, METHOD_BUFFERED) #define TAP_WIN_IOCTL_CONFIG_DHCP_MASQ TAP_WIN_CONTROL_CODE (7, METHOD_BUFFERED) #define TAP_WIN_IOCTL_GET_LOG_LINE TAP_WIN_CONTROL_CODE (8, METHOD_BUFFERED) #define TAP_WIN_IOCTL_CONFIG_DHCP_SET_OPT TAP_WIN_CONTROL_CODE (9, METHOD_BUFFERED) /* Added in 8.2 */ /* obsoletes TAP_WIN_IOCTL_CONFIG_POINT_TO_POINT */ #define TAP_WIN_IOCTL_CONFIG_TUN TAP_WIN_CONTROL_CODE (10, METHOD_BUFFERED) /* Control whether 802.1Q headers are added for priority */ #define TAP_WIN_IOCTL_PRIORITY_BEHAVIOR TAP_WIN_CONTROL_CODE (11, METHOD_BUFFERED) #define TAP_PRIORITY_BEHAVIOR_NOPRIORITY 0 #define TAP_PRIORITY_BEHAVIOR_ENABLED 1 #define TAP_PRIORITY_BEHAVIOR_ADDALWAYS 2 #define TAP_PRIORITY_BEHAVIOR_MAX 2 /* * ================= * Registry keys * ================= */ #define ADAPTER_KEY "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}" #define NETWORK_CONNECTIONS_KEY "SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}" /* * ====================== * Filesystem prefixes * ====================== */ #define USERMODEDEVICEDIR "\\\\.\\Global\\" #define SYSDEVICEDIR "\\Device\\" #define USERDEVICEDIR "\\DosDevices\\Global\\" #define TAP_WIN_SUFFIX ".tap" #endif // __TAP_WIN_H opengnb-ver1.6.0.a/libs/wintun/000077500000000000000000000000001500454252100163555ustar00rootroot00000000000000opengnb-ver1.6.0.a/libs/wintun/wintun.h000066400000000000000000000241721500454252100200600ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-2.0 OR MIT * * Copyright (C) 2018-2021 WireGuard LLC. All Rights Reserved. */ #pragma once #include #include #include #include #include #ifdef __cplusplus extern "C" { #endif #ifndef ALIGNED # if defined(_MSC_VER) # define ALIGNED(n) __declspec(align(n)) # elif defined(__GNUC__) # define ALIGNED(n) __attribute__((aligned(n))) # else # error "Unable to define ALIGNED" # endif #endif /* MinGW is missing this one, unfortunately. */ #ifndef _Post_maybenull_ # define _Post_maybenull_ #endif #pragma warning(push) #pragma warning(disable : 4324) /* structure was padded due to alignment specifier */ /** * A handle representing Wintun adapter */ typedef struct _WINTUN_ADAPTER *WINTUN_ADAPTER_HANDLE; /** * Creates a new Wintun adapter. * * @param Name The requested name of the adapter. Zero-terminated string of up to MAX_ADAPTER_NAME-1 * characters. * * @param TunnelType Name of the adapter tunnel type. Zero-terminated string of up to MAX_ADAPTER_NAME-1 * characters. * * @param RequestedGUID The GUID of the created network adapter, which then influences NLA generation deterministically. * If it is set to NULL, the GUID is chosen by the system at random, and hence a new NLA entry is * created for each new adapter. It is called "requested" GUID because the API it uses is * completely undocumented, and so there could be minor interesting complications with its usage. * * @return If the function succeeds, the return value is the adapter handle. Must be released with * WintunCloseAdapter. If the function fails, the return value is NULL. To get extended error information, call * GetLastError. */ typedef _Must_inspect_result_ _Return_type_success_(return != NULL) _Post_maybenull_ WINTUN_ADAPTER_HANDLE(WINAPI WINTUN_CREATE_ADAPTER_FUNC) (_In_z_ LPCWSTR Name, _In_z_ LPCWSTR TunnelType, _In_opt_ const GUID *RequestedGUID); /** * Opens an existing Wintun adapter. * * @param Name The requested name of the adapter. Zero-terminated string of up to MAX_ADAPTER_NAME-1 * characters. * * @return If the function succeeds, the return value is the adapter handle. Must be released with * WintunCloseAdapter. If the function fails, the return value is NULL. To get extended error information, call * GetLastError. */ typedef _Must_inspect_result_ _Return_type_success_(return != NULL) _Post_maybenull_ WINTUN_ADAPTER_HANDLE(WINAPI WINTUN_OPEN_ADAPTER_FUNC)(_In_z_ LPCWSTR Name); /** * Releases Wintun adapter resources and, if adapter was created with WintunCreateAdapter, removes adapter. * * @param Adapter Adapter handle obtained with WintunCreateAdapter or WintunOpenAdapter. */ typedef VOID(WINAPI WINTUN_CLOSE_ADAPTER_FUNC)(_In_opt_ WINTUN_ADAPTER_HANDLE Adapter); /** * Deletes the Wintun driver if there are no more adapters in use. * * @return If the function succeeds, the return value is nonzero. If the function fails, the return value is zero. To * get extended error information, call GetLastError. */ typedef _Return_type_success_(return != FALSE) BOOL(WINAPI WINTUN_DELETE_DRIVER_FUNC)(VOID); /** * Returns the LUID of the adapter. * * @param Adapter Adapter handle obtained with WintunCreateAdapter or WintunOpenAdapter * * @param Luid Pointer to LUID to receive adapter LUID. */ typedef VOID(WINAPI WINTUN_GET_ADAPTER_LUID_FUNC)(_In_ WINTUN_ADAPTER_HANDLE Adapter, _Out_ NET_LUID *Luid); /** * Determines the version of the Wintun driver currently loaded. * * @return If the function succeeds, the return value is the version number. If the function fails, the return value is * zero. To get extended error information, call GetLastError. Possible errors include the following: * ERROR_FILE_NOT_FOUND Wintun not loaded */ typedef _Return_type_success_(return != 0) DWORD(WINAPI WINTUN_GET_RUNNING_DRIVER_VERSION_FUNC)(VOID); /** * Determines the level of logging, passed to WINTUN_LOGGER_CALLBACK. */ typedef enum { WINTUN_LOG_INFO, /**< Informational */ WINTUN_LOG_WARN, /**< Warning */ WINTUN_LOG_ERR /**< Error */ } WINTUN_LOGGER_LEVEL; /** * Called by internal logger to report diagnostic messages * * @param Level Message level. * * @param Timestamp Message timestamp in in 100ns intervals since 1601-01-01 UTC. * * @param Message Message text. */ typedef VOID(CALLBACK *WINTUN_LOGGER_CALLBACK)( _In_ WINTUN_LOGGER_LEVEL Level, _In_ DWORD64 Timestamp, _In_z_ LPCWSTR Message); /** * Sets logger callback function. * * @param NewLogger Pointer to callback function to use as a new global logger. NewLogger may be called from various * threads concurrently. Should the logging require serialization, you must handle serialization in * NewLogger. Set to NULL to disable. */ typedef VOID(WINAPI WINTUN_SET_LOGGER_FUNC)(_In_ WINTUN_LOGGER_CALLBACK NewLogger); /** * Minimum ring capacity. */ #define WINTUN_MIN_RING_CAPACITY 0x20000 /* 128kiB */ /** * Maximum ring capacity. */ #define WINTUN_MAX_RING_CAPACITY 0x4000000 /* 64MiB */ /** * A handle representing Wintun session */ typedef struct _TUN_SESSION *WINTUN_SESSION_HANDLE; /** * Starts Wintun session. * * @param Adapter Adapter handle obtained with WintunOpenAdapter or WintunCreateAdapter * * @param Capacity Rings capacity. Must be between WINTUN_MIN_RING_CAPACITY and WINTUN_MAX_RING_CAPACITY (incl.) * Must be a power of two. * * @return Wintun session handle. Must be released with WintunEndSession. If the function fails, the return value is * NULL. To get extended error information, call GetLastError. */ typedef _Must_inspect_result_ _Return_type_success_(return != NULL) _Post_maybenull_ WINTUN_SESSION_HANDLE(WINAPI WINTUN_START_SESSION_FUNC)(_In_ WINTUN_ADAPTER_HANDLE Adapter, _In_ DWORD Capacity); /** * Ends Wintun session. * * @param Session Wintun session handle obtained with WintunStartSession */ typedef VOID(WINAPI WINTUN_END_SESSION_FUNC)(_In_ WINTUN_SESSION_HANDLE Session); /** * Gets Wintun session's read-wait event handle. * * @param Session Wintun session handle obtained with WintunStartSession * * @return Pointer to receive event handle to wait for available data when reading. Should * WintunReceivePackets return ERROR_NO_MORE_ITEMS (after spinning on it for a while under heavy * load), wait for this event to become signaled before retrying WintunReceivePackets. Do not call * CloseHandle on this event - it is managed by the session. */ typedef HANDLE(WINAPI WINTUN_GET_READ_WAIT_EVENT_FUNC)(_In_ WINTUN_SESSION_HANDLE Session); /** * Maximum IP packet size */ #define WINTUN_MAX_IP_PACKET_SIZE 0xFFFF /** * Retrieves one or packet. After the packet content is consumed, call WintunReleaseReceivePacket with Packet returned * from this function to release internal buffer. This function is thread-safe. * * @param Session Wintun session handle obtained with WintunStartSession * * @param PacketSize Pointer to receive packet size. * * @return Pointer to layer 3 IPv4 or IPv6 packet. Client may modify its content at will. If the function fails, the * return value is NULL. To get extended error information, call GetLastError. Possible errors include the * following: * ERROR_HANDLE_EOF Wintun adapter is terminating; * ERROR_NO_MORE_ITEMS Wintun buffer is exhausted; * ERROR_INVALID_DATA Wintun buffer is corrupt */ typedef _Must_inspect_result_ _Return_type_success_(return != NULL) _Post_maybenull_ _Post_writable_byte_size_(*PacketSize) BYTE *(WINAPI WINTUN_RECEIVE_PACKET_FUNC)(_In_ WINTUN_SESSION_HANDLE Session, _Out_ DWORD *PacketSize); /** * Releases internal buffer after the received packet has been processed by the client. This function is thread-safe. * * @param Session Wintun session handle obtained with WintunStartSession * * @param Packet Packet obtained with WintunReceivePacket */ typedef VOID( WINAPI WINTUN_RELEASE_RECEIVE_PACKET_FUNC)(_In_ WINTUN_SESSION_HANDLE Session, _In_ const BYTE *Packet); /** * Allocates memory for a packet to send. After the memory is filled with packet data, call WintunSendPacket to send * and release internal buffer. WintunAllocateSendPacket is thread-safe and the WintunAllocateSendPacket order of * calls define the packet sending order. * * @param Session Wintun session handle obtained with WintunStartSession * * @param PacketSize Exact packet size. Must be less or equal to WINTUN_MAX_IP_PACKET_SIZE. * * @return Returns pointer to memory where to prepare layer 3 IPv4 or IPv6 packet for sending. If the function fails, * the return value is NULL. To get extended error information, call GetLastError. Possible errors include the * following: * ERROR_HANDLE_EOF Wintun adapter is terminating; * ERROR_BUFFER_OVERFLOW Wintun buffer is full; */ typedef _Must_inspect_result_ _Return_type_success_(return != NULL) _Post_maybenull_ _Post_writable_byte_size_(PacketSize) BYTE *(WINAPI WINTUN_ALLOCATE_SEND_PACKET_FUNC)(_In_ WINTUN_SESSION_HANDLE Session, _In_ DWORD PacketSize); /** * Sends the packet and releases internal buffer. WintunSendPacket is thread-safe, but the WintunAllocateSendPacket * order of calls define the packet sending order. This means the packet is not guaranteed to be sent in the * WintunSendPacket yet. * * @param Session Wintun session handle obtained with WintunStartSession * * @param Packet Packet obtained with WintunAllocateSendPacket */ typedef VOID(WINAPI WINTUN_SEND_PACKET_FUNC)(_In_ WINTUN_SESSION_HANDLE Session, _In_ const BYTE *Packet); #pragma warning(pop) #ifdef __cplusplus } #endif opengnb-ver1.6.0.a/libs/zlib/000077500000000000000000000000001500454252100157715ustar00rootroot00000000000000opengnb-ver1.6.0.a/libs/zlib/LICENSE000066400000000000000000000017521500454252100170030ustar00rootroot00000000000000Copyright notice: (C) 1995-2022 Jean-loup Gailly and Mark Adler This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. Jean-loup Gailly Mark Adler jloup@gzip.org madler@alumni.caltech.edu opengnb-ver1.6.0.a/libs/zlib/adler32.c000066400000000000000000000115441500454252100173760ustar00rootroot00000000000000/* adler32.c -- compute the Adler-32 checksum of a data stream * Copyright (C) 1995-2011, 2016 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ /* @(#) $Id$ */ #include "zutil.h" #define BASE 65521U /* largest prime smaller than 65536 */ #define NMAX 5552 /* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ #define DO1(buf,i) {adler += (buf)[i]; sum2 += adler;} #define DO2(buf,i) DO1(buf,i); DO1(buf,i+1); #define DO4(buf,i) DO2(buf,i); DO2(buf,i+2); #define DO8(buf,i) DO4(buf,i); DO4(buf,i+4); #define DO16(buf) DO8(buf,0); DO8(buf,8); /* use NO_DIVIDE if your processor does not do division in hardware -- try it both ways to see which is faster */ #ifdef NO_DIVIDE /* note that this assumes BASE is 65521, where 65536 % 65521 == 15 (thank you to John Reiser for pointing this out) */ # define CHOP(a) \ do { \ unsigned long tmp = a >> 16; \ a &= 0xffffUL; \ a += (tmp << 4) - tmp; \ } while (0) # define MOD28(a) \ do { \ CHOP(a); \ if (a >= BASE) a -= BASE; \ } while (0) # define MOD(a) \ do { \ CHOP(a); \ MOD28(a); \ } while (0) # define MOD63(a) \ do { /* this assumes a is not negative */ \ z_off64_t tmp = a >> 32; \ a &= 0xffffffffL; \ a += (tmp << 8) - (tmp << 5) + tmp; \ tmp = a >> 16; \ a &= 0xffffL; \ a += (tmp << 4) - tmp; \ tmp = a >> 16; \ a &= 0xffffL; \ a += (tmp << 4) - tmp; \ if (a >= BASE) a -= BASE; \ } while (0) #else # define MOD(a) a %= BASE # define MOD28(a) a %= BASE # define MOD63(a) a %= BASE #endif /* ========================================================================= */ uLong ZEXPORT adler32_z(uLong adler, const Bytef *buf, z_size_t len) { unsigned long sum2; unsigned n; /* split Adler-32 into component sums */ sum2 = (adler >> 16) & 0xffff; adler &= 0xffff; /* in case user likes doing a byte at a time, keep it fast */ if (len == 1) { adler += buf[0]; if (adler >= BASE) adler -= BASE; sum2 += adler; if (sum2 >= BASE) sum2 -= BASE; return adler | (sum2 << 16); } /* initial Adler-32 value (deferred check for len == 1 speed) */ if (buf == Z_NULL) return 1L; /* in case short lengths are provided, keep it somewhat fast */ if (len < 16) { while (len--) { adler += *buf++; sum2 += adler; } if (adler >= BASE) adler -= BASE; MOD28(sum2); /* only added so many BASE's */ return adler | (sum2 << 16); } /* do length NMAX blocks -- requires just one modulo operation */ while (len >= NMAX) { len -= NMAX; n = NMAX / 16; /* NMAX is divisible by 16 */ do { DO16(buf); /* 16 sums unrolled */ buf += 16; } while (--n); MOD(adler); MOD(sum2); } /* do remaining bytes (less than NMAX, still just one modulo) */ if (len) { /* avoid modulos if none remaining */ while (len >= 16) { len -= 16; DO16(buf); buf += 16; } while (len--) { adler += *buf++; sum2 += adler; } MOD(adler); MOD(sum2); } /* return recombined sums */ return adler | (sum2 << 16); } /* ========================================================================= */ uLong ZEXPORT adler32(uLong adler, const Bytef *buf, uInt len) { return adler32_z(adler, buf, len); } /* ========================================================================= */ local uLong adler32_combine_(uLong adler1, uLong adler2, z_off64_t len2) { unsigned long sum1; unsigned long sum2; unsigned rem; /* for negative len, return invalid adler32 as a clue for debugging */ if (len2 < 0) return 0xffffffffUL; /* the derivation of this formula is left as an exercise for the reader */ MOD63(len2); /* assumes len2 >= 0 */ rem = (unsigned)len2; sum1 = adler1 & 0xffff; sum2 = rem * sum1; MOD(sum2); sum1 += (adler2 & 0xffff) + BASE - 1; sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem; if (sum1 >= BASE) sum1 -= BASE; if (sum1 >= BASE) sum1 -= BASE; if (sum2 >= ((unsigned long)BASE << 1)) sum2 -= ((unsigned long)BASE << 1); if (sum2 >= BASE) sum2 -= BASE; return sum1 | (sum2 << 16); } /* ========================================================================= */ uLong ZEXPORT adler32_combine(uLong adler1, uLong adler2, z_off_t len2) { return adler32_combine_(adler1, adler2, len2); } uLong ZEXPORT adler32_combine64(uLong adler1, uLong adler2, z_off64_t len2) { return adler32_combine_(adler1, adler2, len2); } opengnb-ver1.6.0.a/libs/zlib/deflate.c000066400000000000000000002375031500454252100175530ustar00rootroot00000000000000/* deflate.c -- compress data using the deflation algorithm * Copyright (C) 1995-2024 Jean-loup Gailly and Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ /* * ALGORITHM * * The "deflation" process depends on being able to identify portions * of the input text which are identical to earlier input (within a * sliding window trailing behind the input currently being processed). * * The most straightforward technique turns out to be the fastest for * most input files: try all possible matches and select the longest. * The key feature of this algorithm is that insertions into the string * dictionary are very simple and thus fast, and deletions are avoided * completely. Insertions are performed at each input character, whereas * string matches are performed only when the previous match ends. So it * is preferable to spend more time in matches to allow very fast string * insertions and avoid deletions. The matching algorithm for small * strings is inspired from that of Rabin & Karp. A brute force approach * is used to find longer strings when a small match has been found. * A similar algorithm is used in comic (by Jan-Mark Wams) and freeze * (by Leonid Broukhis). * A previous version of this file used a more sophisticated algorithm * (by Fiala and Greene) which is guaranteed to run in linear amortized * time, but has a larger average cost, uses more memory and is patented. * However the F&G algorithm may be faster for some highly redundant * files if the parameter max_chain_length (described below) is too large. * * ACKNOWLEDGEMENTS * * The idea of lazy evaluation of matches is due to Jan-Mark Wams, and * I found it in 'freeze' written by Leonid Broukhis. * Thanks to many people for bug reports and testing. * * REFERENCES * * Deutsch, L.P.,"DEFLATE Compressed Data Format Specification". * Available in http://tools.ietf.org/html/rfc1951 * * A description of the Rabin and Karp algorithm is given in the book * "Algorithms" by R. Sedgewick, Addison-Wesley, p252. * * Fiala,E.R., and Greene,D.H. * Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595 * */ /* @(#) $Id$ */ #include "deflate.h" const char deflate_copyright[] = " deflate 1.3.1 Copyright 1995-2024 Jean-loup Gailly and Mark Adler "; /* If you use the zlib library in a product, an acknowledgment is welcome in the documentation of your product. If for some reason you cannot include such an acknowledgment, I would appreciate that you keep this copyright string in the executable of your product. */ typedef enum { need_more, /* block not completed, need more input or more output */ block_done, /* block flush performed */ finish_started, /* finish started, need only more output at next deflate */ finish_done /* finish done, accept no more input or output */ } block_state; typedef block_state (*compress_func)(deflate_state *s, int flush); /* Compression function. Returns the block state after the call. */ local block_state deflate_stored(deflate_state *s, int flush); local block_state deflate_fast(deflate_state *s, int flush); #ifndef FASTEST local block_state deflate_slow(deflate_state *s, int flush); #endif local block_state deflate_rle(deflate_state *s, int flush); local block_state deflate_huff(deflate_state *s, int flush); /* =========================================================================== * Local data */ #define NIL 0 /* Tail of hash chains */ #ifndef TOO_FAR # define TOO_FAR 4096 #endif /* Matches of length 3 are discarded if their distance exceeds TOO_FAR */ /* Values for max_lazy_match, good_match and max_chain_length, depending on * the desired pack level (0..9). The values given below have been tuned to * exclude worst case performance for pathological files. Better values may be * found for specific files. */ typedef struct config_s { ush good_length; /* reduce lazy search above this match length */ ush max_lazy; /* do not perform lazy search above this match length */ ush nice_length; /* quit search above this match length */ ush max_chain; compress_func func; } config; #ifdef FASTEST local const config configuration_table[2] = { /* good lazy nice chain */ /* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ /* 1 */ {4, 4, 8, 4, deflate_fast}}; /* max speed, no lazy matches */ #else local const config configuration_table[10] = { /* good lazy nice chain */ /* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ /* 1 */ {4, 4, 8, 4, deflate_fast}, /* max speed, no lazy matches */ /* 2 */ {4, 5, 16, 8, deflate_fast}, /* 3 */ {4, 6, 32, 32, deflate_fast}, /* 4 */ {4, 4, 16, 16, deflate_slow}, /* lazy matches */ /* 5 */ {8, 16, 32, 32, deflate_slow}, /* 6 */ {8, 16, 128, 128, deflate_slow}, /* 7 */ {8, 32, 128, 256, deflate_slow}, /* 8 */ {32, 128, 258, 1024, deflate_slow}, /* 9 */ {32, 258, 258, 4096, deflate_slow}}; /* max compression */ #endif /* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4 * For deflate_fast() (levels <= 3) good is ignored and lazy has a different * meaning. */ /* rank Z_BLOCK between Z_NO_FLUSH and Z_PARTIAL_FLUSH */ #define RANK(f) (((f) * 2) - ((f) > 4 ? 9 : 0)) /* =========================================================================== * Update a hash value with the given input byte * IN assertion: all calls to UPDATE_HASH are made with consecutive input * characters, so that a running hash key can be computed from the previous * key instead of complete recalculation each time. */ #define UPDATE_HASH(s,h,c) (h = (((h) << s->hash_shift) ^ (c)) & s->hash_mask) /* =========================================================================== * Insert string str in the dictionary and set match_head to the previous head * of the hash chain (the most recent string with same hash key). Return * the previous length of the hash chain. * If this file is compiled with -DFASTEST, the compression level is forced * to 1, and no hash chains are maintained. * IN assertion: all calls to INSERT_STRING are made with consecutive input * characters and the first MIN_MATCH bytes of str are valid (except for * the last MIN_MATCH-1 bytes of the input file). */ #ifdef FASTEST #define INSERT_STRING(s, str, match_head) \ (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ match_head = s->head[s->ins_h], \ s->head[s->ins_h] = (Pos)(str)) #else #define INSERT_STRING(s, str, match_head) \ (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ match_head = s->prev[(str) & s->w_mask] = s->head[s->ins_h], \ s->head[s->ins_h] = (Pos)(str)) #endif /* =========================================================================== * Initialize the hash table (avoiding 64K overflow for 16 bit systems). * prev[] will be initialized on the fly. */ #define CLEAR_HASH(s) \ do { \ s->head[s->hash_size - 1] = NIL; \ zmemzero((Bytef *)s->head, \ (unsigned)(s->hash_size - 1)*sizeof(*s->head)); \ } while (0) /* =========================================================================== * Slide the hash table when sliding the window down (could be avoided with 32 * bit values at the expense of memory usage). We slide even when level == 0 to * keep the hash table consistent if we switch back to level > 0 later. */ #if defined(__has_feature) # if __has_feature(memory_sanitizer) __attribute__((no_sanitize("memory"))) # endif #endif local void slide_hash(deflate_state *s) { unsigned n, m; Posf *p; uInt wsize = s->w_size; n = s->hash_size; p = &s->head[n]; do { m = *--p; *p = (Pos)(m >= wsize ? m - wsize : NIL); } while (--n); n = wsize; #ifndef FASTEST p = &s->prev[n]; do { m = *--p; *p = (Pos)(m >= wsize ? m - wsize : NIL); /* If n is not on any hash chain, prev[n] is garbage but * its value will never be used. */ } while (--n); #endif } /* =========================================================================== * Read a new buffer from the current input stream, update the adler32 * and total number of bytes read. All deflate() input goes through * this function so some applications may wish to modify it to avoid * allocating a large strm->next_in buffer and copying from it. * (See also flush_pending()). */ local unsigned read_buf(z_streamp strm, Bytef *buf, unsigned size) { unsigned len = strm->avail_in; if (len > size) len = size; if (len == 0) return 0; strm->avail_in -= len; zmemcpy(buf, strm->next_in, len); if (strm->state->wrap == 1) { strm->adler = adler32(strm->adler, buf, len); } #ifdef GZIP else if (strm->state->wrap == 2) { strm->adler = crc32(strm->adler, buf, len); } #endif strm->next_in += len; strm->total_in += len; return len; } /* =========================================================================== * Fill the window when the lookahead becomes insufficient. * Updates strstart and lookahead. * * IN assertion: lookahead < MIN_LOOKAHEAD * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD * At least one byte has been read, or avail_in == 0; reads are * performed for at least two bytes (required for the zip translate_eol * option -- not supported here). */ local void fill_window(deflate_state *s) { unsigned n; unsigned more; /* Amount of free space at the end of the window. */ uInt wsize = s->w_size; Assert(s->lookahead < MIN_LOOKAHEAD, "already enough lookahead"); do { more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart); /* Deal with !@#$% 64K limit: */ if (sizeof(int) <= 2) { if (more == 0 && s->strstart == 0 && s->lookahead == 0) { more = wsize; } else if (more == (unsigned)(-1)) { /* Very unlikely, but possible on 16 bit machine if * strstart == 0 && lookahead == 1 (input done a byte at time) */ more--; } } /* If the window is almost full and there is insufficient lookahead, * move the upper half to the lower one to make room in the upper half. */ if (s->strstart >= wsize + MAX_DIST(s)) { zmemcpy(s->window, s->window + wsize, (unsigned)wsize - more); s->match_start -= wsize; s->strstart -= wsize; /* we now have strstart >= MAX_DIST */ s->block_start -= (long) wsize; if (s->insert > s->strstart) s->insert = s->strstart; slide_hash(s); more += wsize; } if (s->strm->avail_in == 0) break; /* If there was no sliding: * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && * more == window_size - lookahead - strstart * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) * => more >= window_size - 2*WSIZE + 2 * In the BIG_MEM or MMAP case (not yet supported), * window_size == input_size + MIN_LOOKAHEAD && * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. * Otherwise, window_size == 2*WSIZE so more >= 2. * If there was sliding, more >= WSIZE. So in all cases, more >= 2. */ Assert(more >= 2, "more < 2"); n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more); s->lookahead += n; /* Initialize the hash value now that we have some input: */ if (s->lookahead + s->insert >= MIN_MATCH) { uInt str = s->strstart - s->insert; s->ins_h = s->window[str]; UPDATE_HASH(s, s->ins_h, s->window[str + 1]); #if MIN_MATCH != 3 Call UPDATE_HASH() MIN_MATCH-3 more times #endif while (s->insert) { UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); #ifndef FASTEST s->prev[str & s->w_mask] = s->head[s->ins_h]; #endif s->head[s->ins_h] = (Pos)str; str++; s->insert--; if (s->lookahead + s->insert < MIN_MATCH) break; } } /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage, * but this is not important since only literal bytes will be emitted. */ } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0); /* If the WIN_INIT bytes after the end of the current data have never been * written, then zero those bytes in order to avoid memory check reports of * the use of uninitialized (or uninitialised as Julian writes) bytes by * the longest match routines. Update the high water mark for the next * time through here. WIN_INIT is set to MAX_MATCH since the longest match * routines allow scanning to strstart + MAX_MATCH, ignoring lookahead. */ if (s->high_water < s->window_size) { ulg curr = s->strstart + (ulg)(s->lookahead); ulg init; if (s->high_water < curr) { /* Previous high water mark below current data -- zero WIN_INIT * bytes or up to end of window, whichever is less. */ init = s->window_size - curr; if (init > WIN_INIT) init = WIN_INIT; zmemzero(s->window + curr, (unsigned)init); s->high_water = curr + init; } else if (s->high_water < (ulg)curr + WIN_INIT) { /* High water mark at or above current data, but below current data * plus WIN_INIT -- zero out to current data plus WIN_INIT, or up * to end of window, whichever is less. */ init = (ulg)curr + WIN_INIT - s->high_water; if (init > s->window_size - s->high_water) init = s->window_size - s->high_water; zmemzero(s->window + s->high_water, (unsigned)init); s->high_water += init; } } Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD, "not enough room for search"); } /* ========================================================================= */ int ZEXPORT deflateInit_(z_streamp strm, int level, const char *version, int stream_size) { return deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, version, stream_size); /* To do: ignore strm->next_in if we use it as window */ } /* ========================================================================= */ int ZEXPORT deflateInit2_(z_streamp strm, int level, int method, int windowBits, int memLevel, int strategy, const char *version, int stream_size) { deflate_state *s; int wrap = 1; static const char my_version[] = ZLIB_VERSION; if (version == Z_NULL || version[0] != my_version[0] || stream_size != sizeof(z_stream)) { return Z_VERSION_ERROR; } if (strm == Z_NULL) return Z_STREAM_ERROR; strm->msg = Z_NULL; if (strm->zalloc == (alloc_func)0) { #ifdef Z_SOLO return Z_STREAM_ERROR; #else strm->zalloc = zcalloc; strm->opaque = (voidpf)0; #endif } if (strm->zfree == (free_func)0) #ifdef Z_SOLO return Z_STREAM_ERROR; #else strm->zfree = zcfree; #endif #ifdef FASTEST if (level != 0) level = 1; #else if (level == Z_DEFAULT_COMPRESSION) level = 6; #endif if (windowBits < 0) { /* suppress zlib wrapper */ wrap = 0; if (windowBits < -15) return Z_STREAM_ERROR; windowBits = -windowBits; } #ifdef GZIP else if (windowBits > 15) { wrap = 2; /* write gzip wrapper instead */ windowBits -= 16; } #endif if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED || windowBits < 8 || windowBits > 15 || level < 0 || level > 9 || strategy < 0 || strategy > Z_FIXED || (windowBits == 8 && wrap != 1)) { return Z_STREAM_ERROR; } if (windowBits == 8) windowBits = 9; /* until 256-byte window bug fixed */ s = (deflate_state *) ZALLOC(strm, 1, sizeof(deflate_state)); if (s == Z_NULL) return Z_MEM_ERROR; strm->state = (struct internal_state FAR *)s; s->strm = strm; s->status = INIT_STATE; /* to pass state test in deflateReset() */ s->wrap = wrap; s->gzhead = Z_NULL; s->w_bits = (uInt)windowBits; s->w_size = 1 << s->w_bits; s->w_mask = s->w_size - 1; s->hash_bits = (uInt)memLevel + 7; s->hash_size = 1 << s->hash_bits; s->hash_mask = s->hash_size - 1; s->hash_shift = ((s->hash_bits + MIN_MATCH-1) / MIN_MATCH); s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte)); s->prev = (Posf *) ZALLOC(strm, s->w_size, sizeof(Pos)); s->head = (Posf *) ZALLOC(strm, s->hash_size, sizeof(Pos)); s->high_water = 0; /* nothing written to s->window yet */ s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */ /* We overlay pending_buf and sym_buf. This works since the average size * for length/distance pairs over any compressed block is assured to be 31 * bits or less. * * Analysis: The longest fixed codes are a length code of 8 bits plus 5 * extra bits, for lengths 131 to 257. The longest fixed distance codes are * 5 bits plus 13 extra bits, for distances 16385 to 32768. The longest * possible fixed-codes length/distance pair is then 31 bits total. * * sym_buf starts one-fourth of the way into pending_buf. So there are * three bytes in sym_buf for every four bytes in pending_buf. Each symbol * in sym_buf is three bytes -- two for the distance and one for the * literal/length. As each symbol is consumed, the pointer to the next * sym_buf value to read moves forward three bytes. From that symbol, up to * 31 bits are written to pending_buf. The closest the written pending_buf * bits gets to the next sym_buf symbol to read is just before the last * code is written. At that time, 31*(n - 2) bits have been written, just * after 24*(n - 2) bits have been consumed from sym_buf. sym_buf starts at * 8*n bits into pending_buf. (Note that the symbol buffer fills when n - 1 * symbols are written.) The closest the writing gets to what is unread is * then n + 14 bits. Here n is lit_bufsize, which is 16384 by default, and * can range from 128 to 32768. * * Therefore, at a minimum, there are 142 bits of space between what is * written and what is read in the overlain buffers, so the symbols cannot * be overwritten by the compressed data. That space is actually 139 bits, * due to the three-bit fixed-code block header. * * That covers the case where either Z_FIXED is specified, forcing fixed * codes, or when the use of fixed codes is chosen, because that choice * results in a smaller compressed block than dynamic codes. That latter * condition then assures that the above analysis also covers all dynamic * blocks. A dynamic-code block will only be chosen to be emitted if it has * fewer bits than a fixed-code block would for the same set of symbols. * Therefore its average symbol length is assured to be less than 31. So * the compressed data for a dynamic block also cannot overwrite the * symbols from which it is being constructed. */ s->pending_buf = (uchf *) ZALLOC(strm, s->lit_bufsize, LIT_BUFS); s->pending_buf_size = (ulg)s->lit_bufsize * 4; if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL || s->pending_buf == Z_NULL) { s->status = FINISH_STATE; strm->msg = ERR_MSG(Z_MEM_ERROR); deflateEnd (strm); return Z_MEM_ERROR; } #ifdef LIT_MEM s->d_buf = (ushf *)(s->pending_buf + (s->lit_bufsize << 1)); s->l_buf = s->pending_buf + (s->lit_bufsize << 2); s->sym_end = s->lit_bufsize - 1; #else s->sym_buf = s->pending_buf + s->lit_bufsize; s->sym_end = (s->lit_bufsize - 1) * 3; #endif /* We avoid equality with lit_bufsize*3 because of wraparound at 64K * on 16 bit machines and because stored blocks are restricted to * 64K-1 bytes. */ s->level = level; s->strategy = strategy; s->method = (Byte)method; return deflateReset(strm); } /* ========================================================================= * Check for a valid deflate stream state. Return 0 if ok, 1 if not. */ local int deflateStateCheck(z_streamp strm) { deflate_state *s; if (strm == Z_NULL || strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0) return 1; s = strm->state; if (s == Z_NULL || s->strm != strm || (s->status != INIT_STATE && #ifdef GZIP s->status != GZIP_STATE && #endif s->status != EXTRA_STATE && s->status != NAME_STATE && s->status != COMMENT_STATE && s->status != HCRC_STATE && s->status != BUSY_STATE && s->status != FINISH_STATE)) return 1; return 0; } /* ========================================================================= */ int ZEXPORT deflateSetDictionary(z_streamp strm, const Bytef *dictionary, uInt dictLength) { deflate_state *s; uInt str, n; int wrap; unsigned avail; z_const unsigned char *next; if (deflateStateCheck(strm) || dictionary == Z_NULL) return Z_STREAM_ERROR; s = strm->state; wrap = s->wrap; if (wrap == 2 || (wrap == 1 && s->status != INIT_STATE) || s->lookahead) return Z_STREAM_ERROR; /* when using zlib wrappers, compute Adler-32 for provided dictionary */ if (wrap == 1) strm->adler = adler32(strm->adler, dictionary, dictLength); s->wrap = 0; /* avoid computing Adler-32 in read_buf */ /* if dictionary would fill window, just replace the history */ if (dictLength >= s->w_size) { if (wrap == 0) { /* already empty otherwise */ CLEAR_HASH(s); s->strstart = 0; s->block_start = 0L; s->insert = 0; } dictionary += dictLength - s->w_size; /* use the tail */ dictLength = s->w_size; } /* insert dictionary into window and hash */ avail = strm->avail_in; next = strm->next_in; strm->avail_in = dictLength; strm->next_in = (z_const Bytef *)dictionary; fill_window(s); while (s->lookahead >= MIN_MATCH) { str = s->strstart; n = s->lookahead - (MIN_MATCH-1); do { UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); #ifndef FASTEST s->prev[str & s->w_mask] = s->head[s->ins_h]; #endif s->head[s->ins_h] = (Pos)str; str++; } while (--n); s->strstart = str; s->lookahead = MIN_MATCH-1; fill_window(s); } s->strstart += s->lookahead; s->block_start = (long)s->strstart; s->insert = s->lookahead; s->lookahead = 0; s->match_length = s->prev_length = MIN_MATCH-1; s->match_available = 0; strm->next_in = next; strm->avail_in = avail; s->wrap = wrap; return Z_OK; } /* ========================================================================= */ int ZEXPORT deflateGetDictionary(z_streamp strm, Bytef *dictionary, uInt *dictLength) { deflate_state *s; uInt len; if (deflateStateCheck(strm)) return Z_STREAM_ERROR; s = strm->state; len = s->strstart + s->lookahead; if (len > s->w_size) len = s->w_size; if (dictionary != Z_NULL && len) zmemcpy(dictionary, s->window + s->strstart + s->lookahead - len, len); if (dictLength != Z_NULL) *dictLength = len; return Z_OK; } /* ========================================================================= */ int ZEXPORT deflateResetKeep(z_streamp strm) { deflate_state *s; if (deflateStateCheck(strm)) { return Z_STREAM_ERROR; } strm->total_in = strm->total_out = 0; strm->msg = Z_NULL; /* use zfree if we ever allocate msg dynamically */ strm->data_type = Z_UNKNOWN; s = (deflate_state *)strm->state; s->pending = 0; s->pending_out = s->pending_buf; if (s->wrap < 0) { s->wrap = -s->wrap; /* was made negative by deflate(..., Z_FINISH); */ } s->status = #ifdef GZIP s->wrap == 2 ? GZIP_STATE : #endif INIT_STATE; strm->adler = #ifdef GZIP s->wrap == 2 ? crc32(0L, Z_NULL, 0) : #endif adler32(0L, Z_NULL, 0); s->last_flush = -2; _tr_init(s); return Z_OK; } /* =========================================================================== * Initialize the "longest match" routines for a new zlib stream */ local void lm_init(deflate_state *s) { s->window_size = (ulg)2L*s->w_size; CLEAR_HASH(s); /* Set the default configuration parameters: */ s->max_lazy_match = configuration_table[s->level].max_lazy; s->good_match = configuration_table[s->level].good_length; s->nice_match = configuration_table[s->level].nice_length; s->max_chain_length = configuration_table[s->level].max_chain; s->strstart = 0; s->block_start = 0L; s->lookahead = 0; s->insert = 0; s->match_length = s->prev_length = MIN_MATCH-1; s->match_available = 0; s->ins_h = 0; } /* ========================================================================= */ int ZEXPORT deflateReset(z_streamp strm) { int ret; ret = deflateResetKeep(strm); if (ret == Z_OK) lm_init(strm->state); return ret; } /* ========================================================================= */ int ZEXPORT deflateSetHeader(z_streamp strm, gz_headerp head) { if (deflateStateCheck(strm) || strm->state->wrap != 2) return Z_STREAM_ERROR; strm->state->gzhead = head; return Z_OK; } /* ========================================================================= */ int ZEXPORT deflatePending(z_streamp strm, unsigned *pending, int *bits) { if (deflateStateCheck(strm)) return Z_STREAM_ERROR; if (pending != Z_NULL) *pending = strm->state->pending; if (bits != Z_NULL) *bits = strm->state->bi_valid; return Z_OK; } /* ========================================================================= */ int ZEXPORT deflatePrime(z_streamp strm, int bits, int value) { deflate_state *s; int put; if (deflateStateCheck(strm)) return Z_STREAM_ERROR; s = strm->state; #ifdef LIT_MEM if (bits < 0 || bits > 16 || (uchf *)s->d_buf < s->pending_out + ((Buf_size + 7) >> 3)) return Z_BUF_ERROR; #else if (bits < 0 || bits > 16 || s->sym_buf < s->pending_out + ((Buf_size + 7) >> 3)) return Z_BUF_ERROR; #endif do { put = Buf_size - s->bi_valid; if (put > bits) put = bits; s->bi_buf |= (ush)((value & ((1 << put) - 1)) << s->bi_valid); s->bi_valid += put; _tr_flush_bits(s); value >>= put; bits -= put; } while (bits); return Z_OK; } /* ========================================================================= */ int ZEXPORT deflateParams(z_streamp strm, int level, int strategy) { deflate_state *s; compress_func func; if (deflateStateCheck(strm)) return Z_STREAM_ERROR; s = strm->state; #ifdef FASTEST if (level != 0) level = 1; #else if (level == Z_DEFAULT_COMPRESSION) level = 6; #endif if (level < 0 || level > 9 || strategy < 0 || strategy > Z_FIXED) { return Z_STREAM_ERROR; } func = configuration_table[s->level].func; if ((strategy != s->strategy || func != configuration_table[level].func) && s->last_flush != -2) { /* Flush the last buffer: */ int err = deflate(strm, Z_BLOCK); if (err == Z_STREAM_ERROR) return err; if (strm->avail_in || (s->strstart - s->block_start) + s->lookahead) return Z_BUF_ERROR; } if (s->level != level) { if (s->level == 0 && s->matches != 0) { if (s->matches == 1) slide_hash(s); else CLEAR_HASH(s); s->matches = 0; } s->level = level; s->max_lazy_match = configuration_table[level].max_lazy; s->good_match = configuration_table[level].good_length; s->nice_match = configuration_table[level].nice_length; s->max_chain_length = configuration_table[level].max_chain; } s->strategy = strategy; return Z_OK; } /* ========================================================================= */ int ZEXPORT deflateTune(z_streamp strm, int good_length, int max_lazy, int nice_length, int max_chain) { deflate_state *s; if (deflateStateCheck(strm)) return Z_STREAM_ERROR; s = strm->state; s->good_match = (uInt)good_length; s->max_lazy_match = (uInt)max_lazy; s->nice_match = nice_length; s->max_chain_length = (uInt)max_chain; return Z_OK; } /* ========================================================================= * For the default windowBits of 15 and memLevel of 8, this function returns a * close to exact, as well as small, upper bound on the compressed size. This * is an expansion of ~0.03%, plus a small constant. * * For any setting other than those defaults for windowBits and memLevel, one * of two worst case bounds is returned. This is at most an expansion of ~4% or * ~13%, plus a small constant. * * Both the 0.03% and 4% derive from the overhead of stored blocks. The first * one is for stored blocks of 16383 bytes (memLevel == 8), whereas the second * is for stored blocks of 127 bytes (the worst case memLevel == 1). The * expansion results from five bytes of header for each stored block. * * The larger expansion of 13% results from a window size less than or equal to * the symbols buffer size (windowBits <= memLevel + 7). In that case some of * the data being compressed may have slid out of the sliding window, impeding * a stored block from being emitted. Then the only choice is a fixed or * dynamic block, where a fixed block limits the maximum expansion to 9 bits * per 8-bit byte, plus 10 bits for every block. The smallest block size for * which this can occur is 255 (memLevel == 2). * * Shifts are used to approximate divisions, for speed. */ uLong ZEXPORT deflateBound(z_streamp strm, uLong sourceLen) { deflate_state *s; uLong fixedlen, storelen, wraplen; /* upper bound for fixed blocks with 9-bit literals and length 255 (memLevel == 2, which is the lowest that may not use stored blocks) -- ~13% overhead plus a small constant */ fixedlen = sourceLen + (sourceLen >> 3) + (sourceLen >> 8) + (sourceLen >> 9) + 4; /* upper bound for stored blocks with length 127 (memLevel == 1) -- ~4% overhead plus a small constant */ storelen = sourceLen + (sourceLen >> 5) + (sourceLen >> 7) + (sourceLen >> 11) + 7; /* if can't get parameters, return larger bound plus a zlib wrapper */ if (deflateStateCheck(strm)) return (fixedlen > storelen ? fixedlen : storelen) + 6; /* compute wrapper length */ s = strm->state; switch (s->wrap) { case 0: /* raw deflate */ wraplen = 0; break; case 1: /* zlib wrapper */ wraplen = 6 + (s->strstart ? 4 : 0); break; #ifdef GZIP case 2: /* gzip wrapper */ wraplen = 18; if (s->gzhead != Z_NULL) { /* user-supplied gzip header */ Bytef *str; if (s->gzhead->extra != Z_NULL) wraplen += 2 + s->gzhead->extra_len; str = s->gzhead->name; if (str != Z_NULL) do { wraplen++; } while (*str++); str = s->gzhead->comment; if (str != Z_NULL) do { wraplen++; } while (*str++); if (s->gzhead->hcrc) wraplen += 2; } break; #endif default: /* for compiler happiness */ wraplen = 6; } /* if not default parameters, return one of the conservative bounds */ if (s->w_bits != 15 || s->hash_bits != 8 + 7) return (s->w_bits <= s->hash_bits && s->level ? fixedlen : storelen) + wraplen; /* default settings: return tight bound for that case -- ~0.03% overhead plus a small constant */ return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + (sourceLen >> 25) + 13 - 6 + wraplen; } /* ========================================================================= * Put a short in the pending buffer. The 16-bit value is put in MSB order. * IN assertion: the stream state is correct and there is enough room in * pending_buf. */ local void putShortMSB(deflate_state *s, uInt b) { put_byte(s, (Byte)(b >> 8)); put_byte(s, (Byte)(b & 0xff)); } /* ========================================================================= * Flush as much pending output as possible. All deflate() output, except for * some deflate_stored() output, goes through this function so some * applications may wish to modify it to avoid allocating a large * strm->next_out buffer and copying into it. (See also read_buf()). */ local void flush_pending(z_streamp strm) { unsigned len; deflate_state *s = strm->state; _tr_flush_bits(s); len = s->pending; if (len > strm->avail_out) len = strm->avail_out; if (len == 0) return; zmemcpy(strm->next_out, s->pending_out, len); strm->next_out += len; s->pending_out += len; strm->total_out += len; strm->avail_out -= len; s->pending -= len; if (s->pending == 0) { s->pending_out = s->pending_buf; } } /* =========================================================================== * Update the header CRC with the bytes s->pending_buf[beg..s->pending - 1]. */ #define HCRC_UPDATE(beg) \ do { \ if (s->gzhead->hcrc && s->pending > (beg)) \ strm->adler = crc32(strm->adler, s->pending_buf + (beg), \ s->pending - (beg)); \ } while (0) /* ========================================================================= */ int ZEXPORT deflate(z_streamp strm, int flush) { int old_flush; /* value of flush param for previous deflate call */ deflate_state *s; if (deflateStateCheck(strm) || flush > Z_BLOCK || flush < 0) { return Z_STREAM_ERROR; } s = strm->state; if (strm->next_out == Z_NULL || (strm->avail_in != 0 && strm->next_in == Z_NULL) || (s->status == FINISH_STATE && flush != Z_FINISH)) { ERR_RETURN(strm, Z_STREAM_ERROR); } if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR); old_flush = s->last_flush; s->last_flush = flush; /* Flush as much pending output as possible */ if (s->pending != 0) { flush_pending(strm); if (strm->avail_out == 0) { /* Since avail_out is 0, deflate will be called again with * more output space, but possibly with both pending and * avail_in equal to zero. There won't be anything to do, * but this is not an error situation so make sure we * return OK instead of BUF_ERROR at next call of deflate: */ s->last_flush = -1; return Z_OK; } /* Make sure there is something to do and avoid duplicate consecutive * flushes. For repeated and useless calls with Z_FINISH, we keep * returning Z_STREAM_END instead of Z_BUF_ERROR. */ } else if (strm->avail_in == 0 && RANK(flush) <= RANK(old_flush) && flush != Z_FINISH) { ERR_RETURN(strm, Z_BUF_ERROR); } /* User must not provide more input after the first FINISH: */ if (s->status == FINISH_STATE && strm->avail_in != 0) { ERR_RETURN(strm, Z_BUF_ERROR); } /* Write the header */ if (s->status == INIT_STATE && s->wrap == 0) s->status = BUSY_STATE; if (s->status == INIT_STATE) { /* zlib header */ uInt header = (Z_DEFLATED + ((s->w_bits - 8) << 4)) << 8; uInt level_flags; if (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2) level_flags = 0; else if (s->level < 6) level_flags = 1; else if (s->level == 6) level_flags = 2; else level_flags = 3; header |= (level_flags << 6); if (s->strstart != 0) header |= PRESET_DICT; header += 31 - (header % 31); putShortMSB(s, header); /* Save the adler32 of the preset dictionary: */ if (s->strstart != 0) { putShortMSB(s, (uInt)(strm->adler >> 16)); putShortMSB(s, (uInt)(strm->adler & 0xffff)); } strm->adler = adler32(0L, Z_NULL, 0); s->status = BUSY_STATE; /* Compression must start with an empty pending buffer */ flush_pending(strm); if (s->pending != 0) { s->last_flush = -1; return Z_OK; } } #ifdef GZIP if (s->status == GZIP_STATE) { /* gzip header */ strm->adler = crc32(0L, Z_NULL, 0); put_byte(s, 31); put_byte(s, 139); put_byte(s, 8); if (s->gzhead == Z_NULL) { put_byte(s, 0); put_byte(s, 0); put_byte(s, 0); put_byte(s, 0); put_byte(s, 0); put_byte(s, s->level == 9 ? 2 : (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? 4 : 0)); put_byte(s, OS_CODE); s->status = BUSY_STATE; /* Compression must start with an empty pending buffer */ flush_pending(strm); if (s->pending != 0) { s->last_flush = -1; return Z_OK; } } else { put_byte(s, (s->gzhead->text ? 1 : 0) + (s->gzhead->hcrc ? 2 : 0) + (s->gzhead->extra == Z_NULL ? 0 : 4) + (s->gzhead->name == Z_NULL ? 0 : 8) + (s->gzhead->comment == Z_NULL ? 0 : 16) ); put_byte(s, (Byte)(s->gzhead->time & 0xff)); put_byte(s, (Byte)((s->gzhead->time >> 8) & 0xff)); put_byte(s, (Byte)((s->gzhead->time >> 16) & 0xff)); put_byte(s, (Byte)((s->gzhead->time >> 24) & 0xff)); put_byte(s, s->level == 9 ? 2 : (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? 4 : 0)); put_byte(s, s->gzhead->os & 0xff); if (s->gzhead->extra != Z_NULL) { put_byte(s, s->gzhead->extra_len & 0xff); put_byte(s, (s->gzhead->extra_len >> 8) & 0xff); } if (s->gzhead->hcrc) strm->adler = crc32(strm->adler, s->pending_buf, s->pending); s->gzindex = 0; s->status = EXTRA_STATE; } } if (s->status == EXTRA_STATE) { if (s->gzhead->extra != Z_NULL) { ulg beg = s->pending; /* start of bytes to update crc */ uInt left = (s->gzhead->extra_len & 0xffff) - s->gzindex; while (s->pending + left > s->pending_buf_size) { uInt copy = s->pending_buf_size - s->pending; zmemcpy(s->pending_buf + s->pending, s->gzhead->extra + s->gzindex, copy); s->pending = s->pending_buf_size; HCRC_UPDATE(beg); s->gzindex += copy; flush_pending(strm); if (s->pending != 0) { s->last_flush = -1; return Z_OK; } beg = 0; left -= copy; } zmemcpy(s->pending_buf + s->pending, s->gzhead->extra + s->gzindex, left); s->pending += left; HCRC_UPDATE(beg); s->gzindex = 0; } s->status = NAME_STATE; } if (s->status == NAME_STATE) { if (s->gzhead->name != Z_NULL) { ulg beg = s->pending; /* start of bytes to update crc */ int val; do { if (s->pending == s->pending_buf_size) { HCRC_UPDATE(beg); flush_pending(strm); if (s->pending != 0) { s->last_flush = -1; return Z_OK; } beg = 0; } val = s->gzhead->name[s->gzindex++]; put_byte(s, val); } while (val != 0); HCRC_UPDATE(beg); s->gzindex = 0; } s->status = COMMENT_STATE; } if (s->status == COMMENT_STATE) { if (s->gzhead->comment != Z_NULL) { ulg beg = s->pending; /* start of bytes to update crc */ int val; do { if (s->pending == s->pending_buf_size) { HCRC_UPDATE(beg); flush_pending(strm); if (s->pending != 0) { s->last_flush = -1; return Z_OK; } beg = 0; } val = s->gzhead->comment[s->gzindex++]; put_byte(s, val); } while (val != 0); HCRC_UPDATE(beg); } s->status = HCRC_STATE; } if (s->status == HCRC_STATE) { if (s->gzhead->hcrc) { if (s->pending + 2 > s->pending_buf_size) { flush_pending(strm); if (s->pending != 0) { s->last_flush = -1; return Z_OK; } } put_byte(s, (Byte)(strm->adler & 0xff)); put_byte(s, (Byte)((strm->adler >> 8) & 0xff)); strm->adler = crc32(0L, Z_NULL, 0); } s->status = BUSY_STATE; /* Compression must start with an empty pending buffer */ flush_pending(strm); if (s->pending != 0) { s->last_flush = -1; return Z_OK; } } #endif /* Start a new block or continue the current one. */ if (strm->avail_in != 0 || s->lookahead != 0 || (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) { block_state bstate; bstate = s->level == 0 ? deflate_stored(s, flush) : s->strategy == Z_HUFFMAN_ONLY ? deflate_huff(s, flush) : s->strategy == Z_RLE ? deflate_rle(s, flush) : (*(configuration_table[s->level].func))(s, flush); if (bstate == finish_started || bstate == finish_done) { s->status = FINISH_STATE; } if (bstate == need_more || bstate == finish_started) { if (strm->avail_out == 0) { s->last_flush = -1; /* avoid BUF_ERROR next call, see above */ } return Z_OK; /* If flush != Z_NO_FLUSH && avail_out == 0, the next call * of deflate should use the same flush parameter to make sure * that the flush is complete. So we don't have to output an * empty block here, this will be done at next call. This also * ensures that for a very small output buffer, we emit at most * one empty block. */ } if (bstate == block_done) { if (flush == Z_PARTIAL_FLUSH) { _tr_align(s); } else if (flush != Z_BLOCK) { /* FULL_FLUSH or SYNC_FLUSH */ _tr_stored_block(s, (char*)0, 0L, 0); /* For a full flush, this empty block will be recognized * as a special marker by inflate_sync(). */ if (flush == Z_FULL_FLUSH) { CLEAR_HASH(s); /* forget history */ if (s->lookahead == 0) { s->strstart = 0; s->block_start = 0L; s->insert = 0; } } } flush_pending(strm); if (strm->avail_out == 0) { s->last_flush = -1; /* avoid BUF_ERROR at next call, see above */ return Z_OK; } } } if (flush != Z_FINISH) return Z_OK; if (s->wrap <= 0) return Z_STREAM_END; /* Write the trailer */ #ifdef GZIP if (s->wrap == 2) { put_byte(s, (Byte)(strm->adler & 0xff)); put_byte(s, (Byte)((strm->adler >> 8) & 0xff)); put_byte(s, (Byte)((strm->adler >> 16) & 0xff)); put_byte(s, (Byte)((strm->adler >> 24) & 0xff)); put_byte(s, (Byte)(strm->total_in & 0xff)); put_byte(s, (Byte)((strm->total_in >> 8) & 0xff)); put_byte(s, (Byte)((strm->total_in >> 16) & 0xff)); put_byte(s, (Byte)((strm->total_in >> 24) & 0xff)); } else #endif { putShortMSB(s, (uInt)(strm->adler >> 16)); putShortMSB(s, (uInt)(strm->adler & 0xffff)); } flush_pending(strm); /* If avail_out is zero, the application will call deflate again * to flush the rest. */ if (s->wrap > 0) s->wrap = -s->wrap; /* write the trailer only once! */ return s->pending != 0 ? Z_OK : Z_STREAM_END; } /* ========================================================================= */ int ZEXPORT deflateEnd(z_streamp strm) { int status; if (deflateStateCheck(strm)) return Z_STREAM_ERROR; status = strm->state->status; /* Deallocate in reverse order of allocations: */ TRY_FREE(strm, strm->state->pending_buf); TRY_FREE(strm, strm->state->head); TRY_FREE(strm, strm->state->prev); TRY_FREE(strm, strm->state->window); ZFREE(strm, strm->state); strm->state = Z_NULL; return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK; } /* ========================================================================= * Copy the source state to the destination state. * To simplify the source, this is not supported for 16-bit MSDOS (which * doesn't have enough memory anyway to duplicate compression states). */ int ZEXPORT deflateCopy(z_streamp dest, z_streamp source) { #ifdef MAXSEG_64K (void)dest; (void)source; return Z_STREAM_ERROR; #else deflate_state *ds; deflate_state *ss; if (deflateStateCheck(source) || dest == Z_NULL) { return Z_STREAM_ERROR; } ss = source->state; zmemcpy((voidpf)dest, (voidpf)source, sizeof(z_stream)); ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state)); if (ds == Z_NULL) return Z_MEM_ERROR; dest->state = (struct internal_state FAR *) ds; zmemcpy((voidpf)ds, (voidpf)ss, sizeof(deflate_state)); ds->strm = dest; ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte)); ds->prev = (Posf *) ZALLOC(dest, ds->w_size, sizeof(Pos)); ds->head = (Posf *) ZALLOC(dest, ds->hash_size, sizeof(Pos)); ds->pending_buf = (uchf *) ZALLOC(dest, ds->lit_bufsize, LIT_BUFS); if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL || ds->pending_buf == Z_NULL) { deflateEnd (dest); return Z_MEM_ERROR; } /* following zmemcpy do not work for 16-bit MSDOS */ zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte)); zmemcpy((voidpf)ds->prev, (voidpf)ss->prev, ds->w_size * sizeof(Pos)); zmemcpy((voidpf)ds->head, (voidpf)ss->head, ds->hash_size * sizeof(Pos)); zmemcpy(ds->pending_buf, ss->pending_buf, ds->lit_bufsize * LIT_BUFS); ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf); #ifdef LIT_MEM ds->d_buf = (ushf *)(ds->pending_buf + (ds->lit_bufsize << 1)); ds->l_buf = ds->pending_buf + (ds->lit_bufsize << 2); #else ds->sym_buf = ds->pending_buf + ds->lit_bufsize; #endif ds->l_desc.dyn_tree = ds->dyn_ltree; ds->d_desc.dyn_tree = ds->dyn_dtree; ds->bl_desc.dyn_tree = ds->bl_tree; return Z_OK; #endif /* MAXSEG_64K */ } #ifndef FASTEST /* =========================================================================== * Set match_start to the longest match starting at the given string and * return its length. Matches shorter or equal to prev_length are discarded, * in which case the result is equal to prev_length and match_start is * garbage. * IN assertions: cur_match is the head of the hash chain for the current * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1 * OUT assertion: the match length is not greater than s->lookahead. */ local uInt longest_match(deflate_state *s, IPos cur_match) { unsigned chain_length = s->max_chain_length;/* max hash chain length */ register Bytef *scan = s->window + s->strstart; /* current string */ register Bytef *match; /* matched string */ register int len; /* length of current match */ int best_len = (int)s->prev_length; /* best match length so far */ int nice_match = s->nice_match; /* stop if match long enough */ IPos limit = s->strstart > (IPos)MAX_DIST(s) ? s->strstart - (IPos)MAX_DIST(s) : NIL; /* Stop when cur_match becomes <= limit. To simplify the code, * we prevent matches with the string of window index 0. */ Posf *prev = s->prev; uInt wmask = s->w_mask; #ifdef UNALIGNED_OK /* Compare two bytes at a time. Note: this is not always beneficial. * Try with and without -DUNALIGNED_OK to check. */ register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1; register ush scan_start = *(ushf*)scan; register ush scan_end = *(ushf*)(scan + best_len - 1); #else register Bytef *strend = s->window + s->strstart + MAX_MATCH; register Byte scan_end1 = scan[best_len - 1]; register Byte scan_end = scan[best_len]; #endif /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. * It is easy to get rid of this optimization if necessary. */ Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); /* Do not waste too much time if we already have a good match: */ if (s->prev_length >= s->good_match) { chain_length >>= 2; } /* Do not look for matches beyond the end of the input. This is necessary * to make deflate deterministic. */ if ((uInt)nice_match > s->lookahead) nice_match = (int)s->lookahead; Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD, "need lookahead"); do { Assert(cur_match < s->strstart, "no future"); match = s->window + cur_match; /* Skip to next match if the match length cannot increase * or if the match length is less than 2. Note that the checks below * for insufficient lookahead only occur occasionally for performance * reasons. Therefore uninitialized memory will be accessed, and * conditional jumps will be made that depend on those values. * However the length of the match is limited to the lookahead, so * the output of deflate is not affected by the uninitialized values. */ #if (defined(UNALIGNED_OK) && MAX_MATCH == 258) /* This code assumes sizeof(unsigned short) == 2. Do not use * UNALIGNED_OK if your compiler uses a different size. */ if (*(ushf*)(match + best_len - 1) != scan_end || *(ushf*)match != scan_start) continue; /* It is not necessary to compare scan[2] and match[2] since they are * always equal when the other bytes match, given that the hash keys * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at * strstart + 3, + 5, up to strstart + 257. We check for insufficient * lookahead only every 4th comparison; the 128th check will be made * at strstart + 257. If MAX_MATCH-2 is not a multiple of 8, it is * necessary to put more guard bytes at the end of the window, or * to check more often for insufficient lookahead. */ Assert(scan[2] == match[2], "scan[2]?"); scan++, match++; do { } while (*(ushf*)(scan += 2) == *(ushf*)(match += 2) && *(ushf*)(scan += 2) == *(ushf*)(match += 2) && *(ushf*)(scan += 2) == *(ushf*)(match += 2) && *(ushf*)(scan += 2) == *(ushf*)(match += 2) && scan < strend); /* The funny "do {}" generates better code on most compilers */ /* Here, scan <= window + strstart + 257 */ Assert(scan <= s->window + (unsigned)(s->window_size - 1), "wild scan"); if (*scan == *match) scan++; len = (MAX_MATCH - 1) - (int)(strend - scan); scan = strend - (MAX_MATCH-1); #else /* UNALIGNED_OK */ if (match[best_len] != scan_end || match[best_len - 1] != scan_end1 || *match != *scan || *++match != scan[1]) continue; /* The check at best_len - 1 can be removed because it will be made * again later. (This heuristic is not always a win.) * It is not necessary to compare scan[2] and match[2] since they * are always equal when the other bytes match, given that * the hash keys are equal and that HASH_BITS >= 8. */ scan += 2, match++; Assert(*scan == *match, "match[2]?"); /* We check for insufficient lookahead only every 8th comparison; * the 256th check will be made at strstart + 258. */ do { } while (*++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && scan < strend); Assert(scan <= s->window + (unsigned)(s->window_size - 1), "wild scan"); len = MAX_MATCH - (int)(strend - scan); scan = strend - MAX_MATCH; #endif /* UNALIGNED_OK */ if (len > best_len) { s->match_start = cur_match; best_len = len; if (len >= nice_match) break; #ifdef UNALIGNED_OK scan_end = *(ushf*)(scan + best_len - 1); #else scan_end1 = scan[best_len - 1]; scan_end = scan[best_len]; #endif } } while ((cur_match = prev[cur_match & wmask]) > limit && --chain_length != 0); if ((uInt)best_len <= s->lookahead) return (uInt)best_len; return s->lookahead; } #else /* FASTEST */ /* --------------------------------------------------------------------------- * Optimized version for FASTEST only */ local uInt longest_match(deflate_state *s, IPos cur_match) { register Bytef *scan = s->window + s->strstart; /* current string */ register Bytef *match; /* matched string */ register int len; /* length of current match */ register Bytef *strend = s->window + s->strstart + MAX_MATCH; /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. * It is easy to get rid of this optimization if necessary. */ Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD, "need lookahead"); Assert(cur_match < s->strstart, "no future"); match = s->window + cur_match; /* Return failure if the match length is less than 2: */ if (match[0] != scan[0] || match[1] != scan[1]) return MIN_MATCH-1; /* The check at best_len - 1 can be removed because it will be made * again later. (This heuristic is not always a win.) * It is not necessary to compare scan[2] and match[2] since they * are always equal when the other bytes match, given that * the hash keys are equal and that HASH_BITS >= 8. */ scan += 2, match += 2; Assert(*scan == *match, "match[2]?"); /* We check for insufficient lookahead only every 8th comparison; * the 256th check will be made at strstart + 258. */ do { } while (*++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && scan < strend); Assert(scan <= s->window + (unsigned)(s->window_size - 1), "wild scan"); len = MAX_MATCH - (int)(strend - scan); if (len < MIN_MATCH) return MIN_MATCH - 1; s->match_start = cur_match; return (uInt)len <= s->lookahead ? (uInt)len : s->lookahead; } #endif /* FASTEST */ #ifdef ZLIB_DEBUG #define EQUAL 0 /* result of memcmp for equal strings */ /* =========================================================================== * Check that the match at match_start is indeed a match. */ local void check_match(deflate_state *s, IPos start, IPos match, int length) { /* check that the match is indeed a match */ Bytef *back = s->window + (int)match, *here = s->window + start; IPos len = length; if (match == (IPos)-1) { /* match starts one byte before the current window -- just compare the subsequent length-1 bytes */ back++; here++; len--; } if (zmemcmp(back, here, len) != EQUAL) { fprintf(stderr, " start %u, match %d, length %d\n", start, (int)match, length); do { fprintf(stderr, "(%02x %02x)", *back++, *here++); } while (--len != 0); z_error("invalid match"); } if (z_verbose > 1) { fprintf(stderr,"\\[%d,%d]", start - match, length); do { putc(s->window[start++], stderr); } while (--length != 0); } } #else # define check_match(s, start, match, length) #endif /* ZLIB_DEBUG */ /* =========================================================================== * Flush the current block, with given end-of-file flag. * IN assertion: strstart is set to the end of the current match. */ #define FLUSH_BLOCK_ONLY(s, last) { \ _tr_flush_block(s, (s->block_start >= 0L ? \ (charf *)&s->window[(unsigned)s->block_start] : \ (charf *)Z_NULL), \ (ulg)((long)s->strstart - s->block_start), \ (last)); \ s->block_start = s->strstart; \ flush_pending(s->strm); \ Tracev((stderr,"[FLUSH]")); \ } /* Same but force premature exit if necessary. */ #define FLUSH_BLOCK(s, last) { \ FLUSH_BLOCK_ONLY(s, last); \ if (s->strm->avail_out == 0) return (last) ? finish_started : need_more; \ } /* Maximum stored block length in deflate format (not including header). */ #define MAX_STORED 65535 /* Minimum of a and b. */ #define MIN(a, b) ((a) > (b) ? (b) : (a)) /* =========================================================================== * Copy without compression as much as possible from the input stream, return * the current block state. * * In case deflateParams() is used to later switch to a non-zero compression * level, s->matches (otherwise unused when storing) keeps track of the number * of hash table slides to perform. If s->matches is 1, then one hash table * slide will be done when switching. If s->matches is 2, the maximum value * allowed here, then the hash table will be cleared, since two or more slides * is the same as a clear. * * deflate_stored() is written to minimize the number of times an input byte is * copied. It is most efficient with large input and output buffers, which * maximizes the opportunities to have a single copy from next_in to next_out. */ local block_state deflate_stored(deflate_state *s, int flush) { /* Smallest worthy block size when not flushing or finishing. By default * this is 32K. This can be as small as 507 bytes for memLevel == 1. For * large input and output buffers, the stored block size will be larger. */ unsigned min_block = MIN(s->pending_buf_size - 5, s->w_size); /* Copy as many min_block or larger stored blocks directly to next_out as * possible. If flushing, copy the remaining available input to next_out as * stored blocks, if there is enough space. */ unsigned len, left, have, last = 0; unsigned used = s->strm->avail_in; do { /* Set len to the maximum size block that we can copy directly with the * available input data and output space. Set left to how much of that * would be copied from what's left in the window. */ len = MAX_STORED; /* maximum deflate stored block length */ have = (s->bi_valid + 42) >> 3; /* number of header bytes */ if (s->strm->avail_out < have) /* need room for header */ break; /* maximum stored block length that will fit in avail_out: */ have = s->strm->avail_out - have; left = s->strstart - s->block_start; /* bytes left in window */ if (len > (ulg)left + s->strm->avail_in) len = left + s->strm->avail_in; /* limit len to the input */ if (len > have) len = have; /* limit len to the output */ /* If the stored block would be less than min_block in length, or if * unable to copy all of the available input when flushing, then try * copying to the window and the pending buffer instead. Also don't * write an empty block when flushing -- deflate() does that. */ if (len < min_block && ((len == 0 && flush != Z_FINISH) || flush == Z_NO_FLUSH || len != left + s->strm->avail_in)) break; /* Make a dummy stored block in pending to get the header bytes, * including any pending bits. This also updates the debugging counts. */ last = flush == Z_FINISH && len == left + s->strm->avail_in ? 1 : 0; _tr_stored_block(s, (char *)0, 0L, last); /* Replace the lengths in the dummy stored block with len. */ s->pending_buf[s->pending - 4] = len; s->pending_buf[s->pending - 3] = len >> 8; s->pending_buf[s->pending - 2] = ~len; s->pending_buf[s->pending - 1] = ~len >> 8; /* Write the stored block header bytes. */ flush_pending(s->strm); #ifdef ZLIB_DEBUG /* Update debugging counts for the data about to be copied. */ s->compressed_len += len << 3; s->bits_sent += len << 3; #endif /* Copy uncompressed bytes from the window to next_out. */ if (left) { if (left > len) left = len; zmemcpy(s->strm->next_out, s->window + s->block_start, left); s->strm->next_out += left; s->strm->avail_out -= left; s->strm->total_out += left; s->block_start += left; len -= left; } /* Copy uncompressed bytes directly from next_in to next_out, updating * the check value. */ if (len) { read_buf(s->strm, s->strm->next_out, len); s->strm->next_out += len; s->strm->avail_out -= len; s->strm->total_out += len; } } while (last == 0); /* Update the sliding window with the last s->w_size bytes of the copied * data, or append all of the copied data to the existing window if less * than s->w_size bytes were copied. Also update the number of bytes to * insert in the hash tables, in the event that deflateParams() switches to * a non-zero compression level. */ used -= s->strm->avail_in; /* number of input bytes directly copied */ if (used) { /* If any input was used, then no unused input remains in the window, * therefore s->block_start == s->strstart. */ if (used >= s->w_size) { /* supplant the previous history */ s->matches = 2; /* clear hash */ zmemcpy(s->window, s->strm->next_in - s->w_size, s->w_size); s->strstart = s->w_size; s->insert = s->strstart; } else { if (s->window_size - s->strstart <= used) { /* Slide the window down. */ s->strstart -= s->w_size; zmemcpy(s->window, s->window + s->w_size, s->strstart); if (s->matches < 2) s->matches++; /* add a pending slide_hash() */ if (s->insert > s->strstart) s->insert = s->strstart; } zmemcpy(s->window + s->strstart, s->strm->next_in - used, used); s->strstart += used; s->insert += MIN(used, s->w_size - s->insert); } s->block_start = s->strstart; } if (s->high_water < s->strstart) s->high_water = s->strstart; /* If the last block was written to next_out, then done. */ if (last) return finish_done; /* If flushing and all input has been consumed, then done. */ if (flush != Z_NO_FLUSH && flush != Z_FINISH && s->strm->avail_in == 0 && (long)s->strstart == s->block_start) return block_done; /* Fill the window with any remaining input. */ have = s->window_size - s->strstart; if (s->strm->avail_in > have && s->block_start >= (long)s->w_size) { /* Slide the window down. */ s->block_start -= s->w_size; s->strstart -= s->w_size; zmemcpy(s->window, s->window + s->w_size, s->strstart); if (s->matches < 2) s->matches++; /* add a pending slide_hash() */ have += s->w_size; /* more space now */ if (s->insert > s->strstart) s->insert = s->strstart; } if (have > s->strm->avail_in) have = s->strm->avail_in; if (have) { read_buf(s->strm, s->window + s->strstart, have); s->strstart += have; s->insert += MIN(have, s->w_size - s->insert); } if (s->high_water < s->strstart) s->high_water = s->strstart; /* There was not enough avail_out to write a complete worthy or flushed * stored block to next_out. Write a stored block to pending instead, if we * have enough input for a worthy block, or if flushing and there is enough * room for the remaining input as a stored block in the pending buffer. */ have = (s->bi_valid + 42) >> 3; /* number of header bytes */ /* maximum stored block length that will fit in pending: */ have = MIN(s->pending_buf_size - have, MAX_STORED); min_block = MIN(have, s->w_size); left = s->strstart - s->block_start; if (left >= min_block || ((left || flush == Z_FINISH) && flush != Z_NO_FLUSH && s->strm->avail_in == 0 && left <= have)) { len = MIN(left, have); last = flush == Z_FINISH && s->strm->avail_in == 0 && len == left ? 1 : 0; _tr_stored_block(s, (charf *)s->window + s->block_start, len, last); s->block_start += len; flush_pending(s->strm); } /* We've done all we can with the available input and output. */ return last ? finish_started : need_more; } /* =========================================================================== * Compress as much as possible from the input stream, return the current * block state. * This function does not perform lazy evaluation of matches and inserts * new strings in the dictionary only for unmatched strings or for short * matches. It is used only for the fast compression options. */ local block_state deflate_fast(deflate_state *s, int flush) { IPos hash_head; /* head of the hash chain */ int bflush; /* set if current block must be flushed */ for (;;) { /* Make sure that we always have enough lookahead, except * at the end of the input file. We need MAX_MATCH bytes * for the next match, plus MIN_MATCH bytes to insert the * string following the next match. */ if (s->lookahead < MIN_LOOKAHEAD) { fill_window(s); if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { return need_more; } if (s->lookahead == 0) break; /* flush the current block */ } /* Insert the string window[strstart .. strstart + 2] in the * dictionary, and set hash_head to the head of the hash chain: */ hash_head = NIL; if (s->lookahead >= MIN_MATCH) { INSERT_STRING(s, s->strstart, hash_head); } /* Find the longest match, discarding those <= prev_length. * At this point we have always match_length < MIN_MATCH */ if (hash_head != NIL && s->strstart - hash_head <= MAX_DIST(s)) { /* To simplify the code, we prevent matches with the string * of window index 0 (in particular we have to avoid a match * of the string with itself at the start of the input file). */ s->match_length = longest_match (s, hash_head); /* longest_match() sets match_start */ } if (s->match_length >= MIN_MATCH) { check_match(s, s->strstart, s->match_start, s->match_length); _tr_tally_dist(s, s->strstart - s->match_start, s->match_length - MIN_MATCH, bflush); s->lookahead -= s->match_length; /* Insert new strings in the hash table only if the match length * is not too large. This saves time but degrades compression. */ #ifndef FASTEST if (s->match_length <= s->max_insert_length && s->lookahead >= MIN_MATCH) { s->match_length--; /* string at strstart already in table */ do { s->strstart++; INSERT_STRING(s, s->strstart, hash_head); /* strstart never exceeds WSIZE-MAX_MATCH, so there are * always MIN_MATCH bytes ahead. */ } while (--s->match_length != 0); s->strstart++; } else #endif { s->strstart += s->match_length; s->match_length = 0; s->ins_h = s->window[s->strstart]; UPDATE_HASH(s, s->ins_h, s->window[s->strstart + 1]); #if MIN_MATCH != 3 Call UPDATE_HASH() MIN_MATCH-3 more times #endif /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not * matter since it will be recomputed at next deflate call. */ } } else { /* No match, output a literal byte */ Tracevv((stderr,"%c", s->window[s->strstart])); _tr_tally_lit(s, s->window[s->strstart], bflush); s->lookahead--; s->strstart++; } if (bflush) FLUSH_BLOCK(s, 0); } s->insert = s->strstart < MIN_MATCH-1 ? s->strstart : MIN_MATCH-1; if (flush == Z_FINISH) { FLUSH_BLOCK(s, 1); return finish_done; } if (s->sym_next) FLUSH_BLOCK(s, 0); return block_done; } #ifndef FASTEST /* =========================================================================== * Same as above, but achieves better compression. We use a lazy * evaluation for matches: a match is finally adopted only if there is * no better match at the next window position. */ local block_state deflate_slow(deflate_state *s, int flush) { IPos hash_head; /* head of hash chain */ int bflush; /* set if current block must be flushed */ /* Process the input block. */ for (;;) { /* Make sure that we always have enough lookahead, except * at the end of the input file. We need MAX_MATCH bytes * for the next match, plus MIN_MATCH bytes to insert the * string following the next match. */ if (s->lookahead < MIN_LOOKAHEAD) { fill_window(s); if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { return need_more; } if (s->lookahead == 0) break; /* flush the current block */ } /* Insert the string window[strstart .. strstart + 2] in the * dictionary, and set hash_head to the head of the hash chain: */ hash_head = NIL; if (s->lookahead >= MIN_MATCH) { INSERT_STRING(s, s->strstart, hash_head); } /* Find the longest match, discarding those <= prev_length. */ s->prev_length = s->match_length, s->prev_match = s->match_start; s->match_length = MIN_MATCH-1; if (hash_head != NIL && s->prev_length < s->max_lazy_match && s->strstart - hash_head <= MAX_DIST(s)) { /* To simplify the code, we prevent matches with the string * of window index 0 (in particular we have to avoid a match * of the string with itself at the start of the input file). */ s->match_length = longest_match (s, hash_head); /* longest_match() sets match_start */ if (s->match_length <= 5 && (s->strategy == Z_FILTERED #if TOO_FAR <= 32767 || (s->match_length == MIN_MATCH && s->strstart - s->match_start > TOO_FAR) #endif )) { /* If prev_match is also MIN_MATCH, match_start is garbage * but we will ignore the current match anyway. */ s->match_length = MIN_MATCH-1; } } /* If there was a match at the previous step and the current * match is not better, output the previous match: */ if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length) { uInt max_insert = s->strstart + s->lookahead - MIN_MATCH; /* Do not insert strings in hash table beyond this. */ check_match(s, s->strstart - 1, s->prev_match, s->prev_length); _tr_tally_dist(s, s->strstart - 1 - s->prev_match, s->prev_length - MIN_MATCH, bflush); /* Insert in hash table all strings up to the end of the match. * strstart - 1 and strstart are already inserted. If there is not * enough lookahead, the last two strings are not inserted in * the hash table. */ s->lookahead -= s->prev_length - 1; s->prev_length -= 2; do { if (++s->strstart <= max_insert) { INSERT_STRING(s, s->strstart, hash_head); } } while (--s->prev_length != 0); s->match_available = 0; s->match_length = MIN_MATCH-1; s->strstart++; if (bflush) FLUSH_BLOCK(s, 0); } else if (s->match_available) { /* If there was no match at the previous position, output a * single literal. If there was a match but the current match * is longer, truncate the previous match to a single literal. */ Tracevv((stderr,"%c", s->window[s->strstart - 1])); _tr_tally_lit(s, s->window[s->strstart - 1], bflush); if (bflush) { FLUSH_BLOCK_ONLY(s, 0); } s->strstart++; s->lookahead--; if (s->strm->avail_out == 0) return need_more; } else { /* There is no previous match to compare with, wait for * the next step to decide. */ s->match_available = 1; s->strstart++; s->lookahead--; } } Assert (flush != Z_NO_FLUSH, "no flush?"); if (s->match_available) { Tracevv((stderr,"%c", s->window[s->strstart - 1])); _tr_tally_lit(s, s->window[s->strstart - 1], bflush); s->match_available = 0; } s->insert = s->strstart < MIN_MATCH-1 ? s->strstart : MIN_MATCH-1; if (flush == Z_FINISH) { FLUSH_BLOCK(s, 1); return finish_done; } if (s->sym_next) FLUSH_BLOCK(s, 0); return block_done; } #endif /* FASTEST */ /* =========================================================================== * For Z_RLE, simply look for runs of bytes, generate matches only of distance * one. Do not maintain a hash table. (It will be regenerated if this run of * deflate switches away from Z_RLE.) */ local block_state deflate_rle(deflate_state *s, int flush) { int bflush; /* set if current block must be flushed */ uInt prev; /* byte at distance one to match */ Bytef *scan, *strend; /* scan goes up to strend for length of run */ for (;;) { /* Make sure that we always have enough lookahead, except * at the end of the input file. We need MAX_MATCH bytes * for the longest run, plus one for the unrolled loop. */ if (s->lookahead <= MAX_MATCH) { fill_window(s); if (s->lookahead <= MAX_MATCH && flush == Z_NO_FLUSH) { return need_more; } if (s->lookahead == 0) break; /* flush the current block */ } /* See how many times the previous byte repeats */ s->match_length = 0; if (s->lookahead >= MIN_MATCH && s->strstart > 0) { scan = s->window + s->strstart - 1; prev = *scan; if (prev == *++scan && prev == *++scan && prev == *++scan) { strend = s->window + s->strstart + MAX_MATCH; do { } while (prev == *++scan && prev == *++scan && prev == *++scan && prev == *++scan && prev == *++scan && prev == *++scan && prev == *++scan && prev == *++scan && scan < strend); s->match_length = MAX_MATCH - (uInt)(strend - scan); if (s->match_length > s->lookahead) s->match_length = s->lookahead; } Assert(scan <= s->window + (uInt)(s->window_size - 1), "wild scan"); } /* Emit match if have run of MIN_MATCH or longer, else emit literal */ if (s->match_length >= MIN_MATCH) { check_match(s, s->strstart, s->strstart - 1, s->match_length); _tr_tally_dist(s, 1, s->match_length - MIN_MATCH, bflush); s->lookahead -= s->match_length; s->strstart += s->match_length; s->match_length = 0; } else { /* No match, output a literal byte */ Tracevv((stderr,"%c", s->window[s->strstart])); _tr_tally_lit(s, s->window[s->strstart], bflush); s->lookahead--; s->strstart++; } if (bflush) FLUSH_BLOCK(s, 0); } s->insert = 0; if (flush == Z_FINISH) { FLUSH_BLOCK(s, 1); return finish_done; } if (s->sym_next) FLUSH_BLOCK(s, 0); return block_done; } /* =========================================================================== * For Z_HUFFMAN_ONLY, do not look for matches. Do not maintain a hash table. * (It will be regenerated if this run of deflate switches away from Huffman.) */ local block_state deflate_huff(deflate_state *s, int flush) { int bflush; /* set if current block must be flushed */ for (;;) { /* Make sure that we have a literal to write. */ if (s->lookahead == 0) { fill_window(s); if (s->lookahead == 0) { if (flush == Z_NO_FLUSH) return need_more; break; /* flush the current block */ } } /* Output a literal byte */ s->match_length = 0; Tracevv((stderr,"%c", s->window[s->strstart])); _tr_tally_lit(s, s->window[s->strstart], bflush); s->lookahead--; s->strstart++; if (bflush) FLUSH_BLOCK(s, 0); } s->insert = 0; if (flush == Z_FINISH) { FLUSH_BLOCK(s, 1); return finish_done; } if (s->sym_next) FLUSH_BLOCK(s, 0); return block_done; } opengnb-ver1.6.0.a/libs/zlib/deflate.h000066400000000000000000000333311500454252100175510ustar00rootroot00000000000000/* deflate.h -- internal compression state * Copyright (C) 1995-2024 Jean-loup Gailly * For conditions of distribution and use, see copyright notice in zlib.h */ /* WARNING: this file should *not* be used by applications. It is part of the implementation of the compression library and is subject to change. Applications should only use zlib.h. */ /* @(#) $Id$ */ #ifndef DEFLATE_H #define DEFLATE_H #include "zutil.h" /* define NO_GZIP when compiling if you want to disable gzip header and trailer creation by deflate(). NO_GZIP would be used to avoid linking in the crc code when it is not needed. For shared libraries, gzip encoding should be left enabled. */ #ifndef NO_GZIP # define GZIP #endif /* define LIT_MEM to slightly increase the speed of deflate (order 1% to 2%) at the cost of a larger memory footprint */ /* #define LIT_MEM */ /* =========================================================================== * Internal compression state. */ #define LENGTH_CODES 29 /* number of length codes, not counting the special END_BLOCK code */ #define LITERALS 256 /* number of literal bytes 0..255 */ #define L_CODES (LITERALS+1+LENGTH_CODES) /* number of Literal or Length codes, including the END_BLOCK code */ #define D_CODES 30 /* number of distance codes */ #define BL_CODES 19 /* number of codes used to transfer the bit lengths */ #define HEAP_SIZE (2*L_CODES+1) /* maximum heap size */ #define MAX_BITS 15 /* All codes must not exceed MAX_BITS bits */ #define Buf_size 16 /* size of bit buffer in bi_buf */ #define INIT_STATE 42 /* zlib header -> BUSY_STATE */ #ifdef GZIP # define GZIP_STATE 57 /* gzip header -> BUSY_STATE | EXTRA_STATE */ #endif #define EXTRA_STATE 69 /* gzip extra block -> NAME_STATE */ #define NAME_STATE 73 /* gzip file name -> COMMENT_STATE */ #define COMMENT_STATE 91 /* gzip comment -> HCRC_STATE */ #define HCRC_STATE 103 /* gzip header CRC -> BUSY_STATE */ #define BUSY_STATE 113 /* deflate -> FINISH_STATE */ #define FINISH_STATE 666 /* stream complete */ /* Stream status */ /* Data structure describing a single value and its code string. */ typedef struct ct_data_s { union { ush freq; /* frequency count */ ush code; /* bit string */ } fc; union { ush dad; /* father node in Huffman tree */ ush len; /* length of bit string */ } dl; } FAR ct_data; #define Freq fc.freq #define Code fc.code #define Dad dl.dad #define Len dl.len typedef struct static_tree_desc_s static_tree_desc; typedef struct tree_desc_s { ct_data *dyn_tree; /* the dynamic tree */ int max_code; /* largest code with non zero frequency */ const static_tree_desc *stat_desc; /* the corresponding static tree */ } FAR tree_desc; typedef ush Pos; typedef Pos FAR Posf; typedef unsigned IPos; /* A Pos is an index in the character window. We use short instead of int to * save space in the various tables. IPos is used only for parameter passing. */ typedef struct internal_state { z_streamp strm; /* pointer back to this zlib stream */ int status; /* as the name implies */ Bytef *pending_buf; /* output still pending */ ulg pending_buf_size; /* size of pending_buf */ Bytef *pending_out; /* next pending byte to output to the stream */ ulg pending; /* nb of bytes in the pending buffer */ int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ gz_headerp gzhead; /* gzip header information to write */ ulg gzindex; /* where in extra, name, or comment */ Byte method; /* can only be DEFLATED */ int last_flush; /* value of flush param for previous deflate call */ /* used by deflate.c: */ uInt w_size; /* LZ77 window size (32K by default) */ uInt w_bits; /* log2(w_size) (8..16) */ uInt w_mask; /* w_size - 1 */ Bytef *window; /* Sliding window. Input bytes are read into the second half of the window, * and move to the first half later to keep a dictionary of at least wSize * bytes. With this organization, matches are limited to a distance of * wSize-MAX_MATCH bytes, but this ensures that IO is always * performed with a length multiple of the block size. Also, it limits * the window size to 64K, which is quite useful on MSDOS. * To do: use the user input buffer as sliding window. */ ulg window_size; /* Actual size of window: 2*wSize, except when the user input buffer * is directly used as sliding window. */ Posf *prev; /* Link to older string with same hash index. To limit the size of this * array to 64K, this link is maintained only for the last 32K strings. * An index in this array is thus a window index modulo 32K. */ Posf *head; /* Heads of the hash chains or NIL. */ uInt ins_h; /* hash index of string to be inserted */ uInt hash_size; /* number of elements in hash table */ uInt hash_bits; /* log2(hash_size) */ uInt hash_mask; /* hash_size-1 */ uInt hash_shift; /* Number of bits by which ins_h must be shifted at each input * step. It must be such that after MIN_MATCH steps, the oldest * byte no longer takes part in the hash key, that is: * hash_shift * MIN_MATCH >= hash_bits */ long block_start; /* Window position at the beginning of the current output block. Gets * negative when the window is moved backwards. */ uInt match_length; /* length of best match */ IPos prev_match; /* previous match */ int match_available; /* set if previous match exists */ uInt strstart; /* start of string to insert */ uInt match_start; /* start of matching string */ uInt lookahead; /* number of valid bytes ahead in window */ uInt prev_length; /* Length of the best match at previous step. Matches not greater than this * are discarded. This is used in the lazy match evaluation. */ uInt max_chain_length; /* To speed up deflation, hash chains are never searched beyond this * length. A higher limit improves compression ratio but degrades the * speed. */ uInt max_lazy_match; /* Attempt to find a better match only when the current match is strictly * smaller than this value. This mechanism is used only for compression * levels >= 4. */ # define max_insert_length max_lazy_match /* Insert new strings in the hash table only if the match length is not * greater than this length. This saves time but degrades compression. * max_insert_length is used only for compression levels <= 3. */ int level; /* compression level (1..9) */ int strategy; /* favor or force Huffman coding*/ uInt good_match; /* Use a faster search when the previous match is longer than this */ int nice_match; /* Stop searching when current match exceeds this */ /* used by trees.c: */ /* Didn't use ct_data typedef below to suppress compiler warning */ struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */ struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */ struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */ struct tree_desc_s l_desc; /* desc. for literal tree */ struct tree_desc_s d_desc; /* desc. for distance tree */ struct tree_desc_s bl_desc; /* desc. for bit length tree */ ush bl_count[MAX_BITS+1]; /* number of codes at each bit length for an optimal tree */ int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */ int heap_len; /* number of elements in the heap */ int heap_max; /* element of largest frequency */ /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. * The same heap array is used to build all trees. */ uch depth[2*L_CODES+1]; /* Depth of each subtree used as tie breaker for trees of equal frequency */ #ifdef LIT_MEM # define LIT_BUFS 5 ushf *d_buf; /* buffer for distances */ uchf *l_buf; /* buffer for literals/lengths */ #else # define LIT_BUFS 4 uchf *sym_buf; /* buffer for distances and literals/lengths */ #endif uInt lit_bufsize; /* Size of match buffer for literals/lengths. There are 4 reasons for * limiting lit_bufsize to 64K: * - frequencies can be kept in 16 bit counters * - if compression is not successful for the first block, all input * data is still in the window so we can still emit a stored block even * when input comes from standard input. (This can also be done for * all blocks if lit_bufsize is not greater than 32K.) * - if compression is not successful for a file smaller than 64K, we can * even emit a stored file instead of a stored block (saving 5 bytes). * This is applicable only for zip (not gzip or zlib). * - creating new Huffman trees less frequently may not provide fast * adaptation to changes in the input data statistics. (Take for * example a binary file with poorly compressible code followed by * a highly compressible string table.) Smaller buffer sizes give * fast adaptation but have of course the overhead of transmitting * trees more frequently. * - I can't count above 4 */ uInt sym_next; /* running index in symbol buffer */ uInt sym_end; /* symbol table full when sym_next reaches this */ ulg opt_len; /* bit length of current block with optimal trees */ ulg static_len; /* bit length of current block with static trees */ uInt matches; /* number of string matches in current block */ uInt insert; /* bytes at end of window left to insert */ #ifdef ZLIB_DEBUG ulg compressed_len; /* total bit length of compressed file mod 2^32 */ ulg bits_sent; /* bit length of compressed data sent mod 2^32 */ #endif ush bi_buf; /* Output buffer. bits are inserted starting at the bottom (least * significant bits). */ int bi_valid; /* Number of valid bits in bi_buf. All bits above the last valid bit * are always zero. */ ulg high_water; /* High water mark offset in window for initialized bytes -- bytes above * this are set to zero in order to avoid memory check warnings when * longest match routines access bytes past the input. This is then * updated to the new high water mark. */ } FAR deflate_state; /* Output a byte on the stream. * IN assertion: there is enough room in pending_buf. */ #define put_byte(s, c) {s->pending_buf[s->pending++] = (Bytef)(c);} #define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) /* Minimum amount of lookahead, except at the end of the input file. * See deflate.c for comments about the MIN_MATCH+1. */ #define MAX_DIST(s) ((s)->w_size-MIN_LOOKAHEAD) /* In order to simplify the code, particularly on 16 bit machines, match * distances are limited to MAX_DIST instead of WSIZE. */ #define WIN_INIT MAX_MATCH /* Number of bytes after end of data in window to initialize in order to avoid memory checker errors from longest match routines */ /* in trees.c */ void ZLIB_INTERNAL _tr_init(deflate_state *s); int ZLIB_INTERNAL _tr_tally(deflate_state *s, unsigned dist, unsigned lc); void ZLIB_INTERNAL _tr_flush_block(deflate_state *s, charf *buf, ulg stored_len, int last); void ZLIB_INTERNAL _tr_flush_bits(deflate_state *s); void ZLIB_INTERNAL _tr_align(deflate_state *s); void ZLIB_INTERNAL _tr_stored_block(deflate_state *s, charf *buf, ulg stored_len, int last); #define d_code(dist) \ ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)]) /* Mapping from a distance to a distance code. dist is the distance - 1 and * must not have side effects. _dist_code[256] and _dist_code[257] are never * used. */ #ifndef ZLIB_DEBUG /* Inline versions of _tr_tally for speed: */ #if defined(GEN_TREES_H) || !defined(STDC) extern uch ZLIB_INTERNAL _length_code[]; extern uch ZLIB_INTERNAL _dist_code[]; #else extern const uch ZLIB_INTERNAL _length_code[]; extern const uch ZLIB_INTERNAL _dist_code[]; #endif #ifdef LIT_MEM # define _tr_tally_lit(s, c, flush) \ { uch cc = (c); \ s->d_buf[s->sym_next] = 0; \ s->l_buf[s->sym_next++] = cc; \ s->dyn_ltree[cc].Freq++; \ flush = (s->sym_next == s->sym_end); \ } # define _tr_tally_dist(s, distance, length, flush) \ { uch len = (uch)(length); \ ush dist = (ush)(distance); \ s->d_buf[s->sym_next] = dist; \ s->l_buf[s->sym_next++] = len; \ dist--; \ s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \ s->dyn_dtree[d_code(dist)].Freq++; \ flush = (s->sym_next == s->sym_end); \ } #else # define _tr_tally_lit(s, c, flush) \ { uch cc = (c); \ s->sym_buf[s->sym_next++] = 0; \ s->sym_buf[s->sym_next++] = 0; \ s->sym_buf[s->sym_next++] = cc; \ s->dyn_ltree[cc].Freq++; \ flush = (s->sym_next == s->sym_end); \ } # define _tr_tally_dist(s, distance, length, flush) \ { uch len = (uch)(length); \ ush dist = (ush)(distance); \ s->sym_buf[s->sym_next++] = (uch)dist; \ s->sym_buf[s->sym_next++] = (uch)(dist >> 8); \ s->sym_buf[s->sym_next++] = len; \ dist--; \ s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \ s->dyn_dtree[d_code(dist)].Freq++; \ flush = (s->sym_next == s->sym_end); \ } #endif #else # define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c) # define _tr_tally_dist(s, distance, length, flush) \ flush = _tr_tally(s, distance, length) #endif #endif /* DEFLATE_H */ opengnb-ver1.6.0.a/libs/zlib/gzguts.h000066400000000000000000000150241500454252100174670ustar00rootroot00000000000000/* gzguts.h -- zlib internal header definitions for gz* operations * Copyright (C) 2004-2024 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ #ifdef _LARGEFILE64_SOURCE # ifndef _LARGEFILE_SOURCE # define _LARGEFILE_SOURCE 1 # endif # undef _FILE_OFFSET_BITS # undef _TIME_BITS #endif #ifdef HAVE_HIDDEN # define ZLIB_INTERNAL __attribute__((visibility ("hidden"))) #else # define ZLIB_INTERNAL #endif #include #include "zlib.h" #ifdef STDC # include # include # include #endif #ifndef _POSIX_SOURCE # define _POSIX_SOURCE #endif #include #ifdef _WIN32 # include #endif #if defined(__TURBOC__) || defined(_MSC_VER) || defined(_WIN32) # include #endif #if defined(_WIN32) # define WIDECHAR #endif #ifdef WINAPI_FAMILY # define open _open # define read _read # define write _write # define close _close #endif #ifdef NO_DEFLATE /* for compatibility with old definition */ # define NO_GZCOMPRESS #endif #if defined(STDC99) || (defined(__TURBOC__) && __TURBOC__ >= 0x550) # ifndef HAVE_VSNPRINTF # define HAVE_VSNPRINTF # endif #endif #if defined(__CYGWIN__) # ifndef HAVE_VSNPRINTF # define HAVE_VSNPRINTF # endif #endif #if defined(MSDOS) && defined(__BORLANDC__) && (BORLANDC > 0x410) # ifndef HAVE_VSNPRINTF # define HAVE_VSNPRINTF # endif #endif #ifndef HAVE_VSNPRINTF # ifdef MSDOS /* vsnprintf may exist on some MS-DOS compilers (DJGPP?), but for now we just assume it doesn't. */ # define NO_vsnprintf # endif # ifdef __TURBOC__ # define NO_vsnprintf # endif # ifdef WIN32 /* In Win32, vsnprintf is available as the "non-ANSI" _vsnprintf. */ # if !defined(vsnprintf) && !defined(NO_vsnprintf) # if !defined(_MSC_VER) || ( defined(_MSC_VER) && _MSC_VER < 1500 ) # define vsnprintf _vsnprintf # endif # endif # endif # ifdef __SASC # define NO_vsnprintf # endif # ifdef VMS # define NO_vsnprintf # endif # ifdef __OS400__ # define NO_vsnprintf # endif # ifdef __MVS__ # define NO_vsnprintf # endif #endif /* unlike snprintf (which is required in C99), _snprintf does not guarantee null termination of the result -- however this is only used in gzlib.c where the result is assured to fit in the space provided */ #if defined(_MSC_VER) && _MSC_VER < 1900 # define snprintf _snprintf #endif #ifndef local # define local static #endif /* since "static" is used to mean two completely different things in C, we define "local" for the non-static meaning of "static", for readability (compile with -Dlocal if your debugger can't find static symbols) */ /* gz* functions always use library allocation functions */ #ifndef STDC extern voidp malloc(uInt size); extern void free(voidpf ptr); #endif /* get errno and strerror definition */ #if defined UNDER_CE # include # define zstrerror() gz_strwinerror((DWORD)GetLastError()) #else # ifndef NO_STRERROR # include # define zstrerror() strerror(errno) # else # define zstrerror() "stdio error (consult errno)" # endif #endif /* provide prototypes for these when building zlib without LFS */ #if !defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0 ZEXTERN gzFile ZEXPORT gzopen64(const char *, const char *); ZEXTERN z_off64_t ZEXPORT gzseek64(gzFile, z_off64_t, int); ZEXTERN z_off64_t ZEXPORT gztell64(gzFile); ZEXTERN z_off64_t ZEXPORT gzoffset64(gzFile); #endif /* default memLevel */ #if MAX_MEM_LEVEL >= 8 # define DEF_MEM_LEVEL 8 #else # define DEF_MEM_LEVEL MAX_MEM_LEVEL #endif /* default i/o buffer size -- double this for output when reading (this and twice this must be able to fit in an unsigned type) */ #define GZBUFSIZE 8192 /* gzip modes, also provide a little integrity check on the passed structure */ #define GZ_NONE 0 #define GZ_READ 7247 #define GZ_WRITE 31153 #define GZ_APPEND 1 /* mode set to GZ_WRITE after the file is opened */ /* values for gz_state how */ #define LOOK 0 /* look for a gzip header */ #define COPY 1 /* copy input directly */ #define GZIP 2 /* decompress a gzip stream */ /* internal gzip file state data structure */ typedef struct { /* exposed contents for gzgetc() macro */ struct gzFile_s x; /* "x" for exposed */ /* x.have: number of bytes available at x.next */ /* x.next: next output data to deliver or write */ /* x.pos: current position in uncompressed data */ /* used for both reading and writing */ int mode; /* see gzip modes above */ int fd; /* file descriptor */ char *path; /* path or fd for error messages */ unsigned size; /* buffer size, zero if not allocated yet */ unsigned want; /* requested buffer size, default is GZBUFSIZE */ unsigned char *in; /* input buffer (double-sized when writing) */ unsigned char *out; /* output buffer (double-sized when reading) */ int direct; /* 0 if processing gzip, 1 if transparent */ /* just for reading */ int how; /* 0: get header, 1: copy, 2: decompress */ z_off64_t start; /* where the gzip data started, for rewinding */ int eof; /* true if end of input file reached */ int past; /* true if read requested past end */ /* just for writing */ int level; /* compression level */ int strategy; /* compression strategy */ int reset; /* true if a reset is pending after a Z_FINISH */ /* seek request */ z_off64_t skip; /* amount to skip (already rewound if backwards) */ int seek; /* true if seek request pending */ /* error information */ int err; /* error code */ char *msg; /* error message */ /* zlib inflate or deflate stream */ z_stream strm; /* stream structure in-place (not a pointer) */ } gz_state; typedef gz_state FAR *gz_statep; /* shared functions */ void ZLIB_INTERNAL gz_error(gz_statep, int, const char *); #if defined UNDER_CE char ZLIB_INTERNAL *gz_strwinerror(DWORD error); #endif /* GT_OFF(x), where x is an unsigned value, is true if x > maximum z_off64_t value -- needed when comparing unsigned to z_off64_t, which is signed (possible z_off64_t types off_t, off64_t, and long are all signed) */ unsigned ZLIB_INTERNAL gz_intmax(void); #define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > gz_intmax()) opengnb-ver1.6.0.a/libs/zlib/inffast.c000066400000000000000000000311741500454252100175750ustar00rootroot00000000000000/* inffast.c -- fast decoding * Copyright (C) 1995-2017 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ #include "zutil.h" #include "inftrees.h" #include "inflate.h" #include "inffast.h" #ifdef ASMINF # pragma message("Assembler code may have bugs -- use at your own risk") #else /* Decode literal, length, and distance codes and write out the resulting literal and match bytes until either not enough input or output is available, an end-of-block is encountered, or a data error is encountered. When large enough input and output buffers are supplied to inflate(), for example, a 16K input buffer and a 64K output buffer, more than 95% of the inflate execution time is spent in this routine. Entry assumptions: state->mode == LEN strm->avail_in >= 6 strm->avail_out >= 258 start >= strm->avail_out state->bits < 8 On return, state->mode is one of: LEN -- ran out of enough output space or enough available input TYPE -- reached end of block code, inflate() to interpret next block BAD -- error in block data Notes: - The maximum input bits used by a length/distance pair is 15 bits for the length code, 5 bits for the length extra, 15 bits for the distance code, and 13 bits for the distance extra. This totals 48 bits, or six bytes. Therefore if strm->avail_in >= 6, then there is enough input to avoid checking for available input while decoding. - The maximum bytes that a single length/distance pair can output is 258 bytes, which is the maximum length that can be coded. inflate_fast() requires strm->avail_out >= 258 for each loop to avoid checking for output space. */ void ZLIB_INTERNAL inflate_fast(z_streamp strm, unsigned start) { struct inflate_state FAR *state; z_const unsigned char FAR *in; /* local strm->next_in */ z_const unsigned char FAR *last; /* have enough input while in < last */ unsigned char FAR *out; /* local strm->next_out */ unsigned char FAR *beg; /* inflate()'s initial strm->next_out */ unsigned char FAR *end; /* while out < end, enough space available */ #ifdef INFLATE_STRICT unsigned dmax; /* maximum distance from zlib header */ #endif unsigned wsize; /* window size or zero if not using window */ unsigned whave; /* valid bytes in the window */ unsigned wnext; /* window write index */ unsigned char FAR *window; /* allocated sliding window, if wsize != 0 */ unsigned long hold; /* local strm->hold */ unsigned bits; /* local strm->bits */ code const FAR *lcode; /* local strm->lencode */ code const FAR *dcode; /* local strm->distcode */ unsigned lmask; /* mask for first level of length codes */ unsigned dmask; /* mask for first level of distance codes */ code const *here; /* retrieved table entry */ unsigned op; /* code bits, operation, extra bits, or */ /* window position, window bytes to copy */ unsigned len; /* match length, unused bytes */ unsigned dist; /* match distance */ unsigned char FAR *from; /* where to copy match from */ /* copy state to local variables */ state = (struct inflate_state FAR *)strm->state; in = strm->next_in; last = in + (strm->avail_in - 5); out = strm->next_out; beg = out - (start - strm->avail_out); end = out + (strm->avail_out - 257); #ifdef INFLATE_STRICT dmax = state->dmax; #endif wsize = state->wsize; whave = state->whave; wnext = state->wnext; window = state->window; hold = state->hold; bits = state->bits; lcode = state->lencode; dcode = state->distcode; lmask = (1U << state->lenbits) - 1; dmask = (1U << state->distbits) - 1; /* decode literals and length/distances until end-of-block or not enough input data or output space */ do { if (bits < 15) { hold += (unsigned long)(*in++) << bits; bits += 8; hold += (unsigned long)(*in++) << bits; bits += 8; } here = lcode + (hold & lmask); dolen: op = (unsigned)(here->bits); hold >>= op; bits -= op; op = (unsigned)(here->op); if (op == 0) { /* literal */ Tracevv((stderr, here->val >= 0x20 && here->val < 0x7f ? "inflate: literal '%c'\n" : "inflate: literal 0x%02x\n", here->val)); *out++ = (unsigned char)(here->val); } else if (op & 16) { /* length base */ len = (unsigned)(here->val); op &= 15; /* number of extra bits */ if (op) { if (bits < op) { hold += (unsigned long)(*in++) << bits; bits += 8; } len += (unsigned)hold & ((1U << op) - 1); hold >>= op; bits -= op; } Tracevv((stderr, "inflate: length %u\n", len)); if (bits < 15) { hold += (unsigned long)(*in++) << bits; bits += 8; hold += (unsigned long)(*in++) << bits; bits += 8; } here = dcode + (hold & dmask); dodist: op = (unsigned)(here->bits); hold >>= op; bits -= op; op = (unsigned)(here->op); if (op & 16) { /* distance base */ dist = (unsigned)(here->val); op &= 15; /* number of extra bits */ if (bits < op) { hold += (unsigned long)(*in++) << bits; bits += 8; if (bits < op) { hold += (unsigned long)(*in++) << bits; bits += 8; } } dist += (unsigned)hold & ((1U << op) - 1); #ifdef INFLATE_STRICT if (dist > dmax) { strm->msg = (char *)"invalid distance too far back"; state->mode = BAD; break; } #endif hold >>= op; bits -= op; Tracevv((stderr, "inflate: distance %u\n", dist)); op = (unsigned)(out - beg); /* max distance in output */ if (dist > op) { /* see if copy from window */ op = dist - op; /* distance back in window */ if (op > whave) { if (state->sane) { strm->msg = (char *)"invalid distance too far back"; state->mode = BAD; break; } #ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR if (len <= op - whave) { do { *out++ = 0; } while (--len); continue; } len -= op - whave; do { *out++ = 0; } while (--op > whave); if (op == 0) { from = out - dist; do { *out++ = *from++; } while (--len); continue; } #endif } from = window; if (wnext == 0) { /* very common case */ from += wsize - op; if (op < len) { /* some from window */ len -= op; do { *out++ = *from++; } while (--op); from = out - dist; /* rest from output */ } } else if (wnext < op) { /* wrap around window */ from += wsize + wnext - op; op -= wnext; if (op < len) { /* some from end of window */ len -= op; do { *out++ = *from++; } while (--op); from = window; if (wnext < len) { /* some from start of window */ op = wnext; len -= op; do { *out++ = *from++; } while (--op); from = out - dist; /* rest from output */ } } } else { /* contiguous in window */ from += wnext - op; if (op < len) { /* some from window */ len -= op; do { *out++ = *from++; } while (--op); from = out - dist; /* rest from output */ } } while (len > 2) { *out++ = *from++; *out++ = *from++; *out++ = *from++; len -= 3; } if (len) { *out++ = *from++; if (len > 1) *out++ = *from++; } } else { from = out - dist; /* copy direct from output */ do { /* minimum length is three */ *out++ = *from++; *out++ = *from++; *out++ = *from++; len -= 3; } while (len > 2); if (len) { *out++ = *from++; if (len > 1) *out++ = *from++; } } } else if ((op & 64) == 0) { /* 2nd level distance code */ here = dcode + here->val + (hold & ((1U << op) - 1)); goto dodist; } else { strm->msg = (char *)"invalid distance code"; state->mode = BAD; break; } } else if ((op & 64) == 0) { /* 2nd level length code */ here = lcode + here->val + (hold & ((1U << op) - 1)); goto dolen; } else if (op & 32) { /* end-of-block */ Tracevv((stderr, "inflate: end of block\n")); state->mode = TYPE; break; } else { strm->msg = (char *)"invalid literal/length code"; state->mode = BAD; break; } } while (in < last && out < end); /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ len = bits >> 3; in -= len; bits -= len << 3; hold &= (1U << bits) - 1; /* update state and return */ strm->next_in = in; strm->next_out = out; strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last)); strm->avail_out = (unsigned)(out < end ? 257 + (end - out) : 257 - (out - end)); state->hold = hold; state->bits = bits; return; } /* inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe): - Using bit fields for code structure - Different op definition to avoid & for extra bits (do & for table bits) - Three separate decoding do-loops for direct, window, and wnext == 0 - Special case for distance > 1 copies to do overlapped load and store copy - Explicit branch predictions (based on measured branch probabilities) - Deferring match copy and interspersed it with decoding subsequent codes - Swapping literal/length else - Swapping window/direct else - Larger unrolled copy loops (three is about right) - Moving len -= 3 statement into middle of loop */ #endif /* !ASMINF */ opengnb-ver1.6.0.a/libs/zlib/inffast.h000066400000000000000000000006461500454252100176020ustar00rootroot00000000000000/* inffast.h -- header to use inffast.c * Copyright (C) 1995-2003, 2010 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ /* WARNING: this file should *not* be used by applications. It is part of the implementation of the compression library and is subject to change. Applications should only use zlib.h. */ void ZLIB_INTERNAL inflate_fast(z_streamp strm, unsigned start); opengnb-ver1.6.0.a/libs/zlib/inffixed.h000066400000000000000000000142741500454252100177460ustar00rootroot00000000000000 /* inffixed.h -- table for decoding fixed codes * Generated automatically by makefixed(). */ /* WARNING: this file should *not* be used by applications. It is part of the implementation of this library and is subject to change. Applications should only use zlib.h. */ static const code lenfix[512] = { {96,7,0},{0,8,80},{0,8,16},{20,8,115},{18,7,31},{0,8,112},{0,8,48}, {0,9,192},{16,7,10},{0,8,96},{0,8,32},{0,9,160},{0,8,0},{0,8,128}, {0,8,64},{0,9,224},{16,7,6},{0,8,88},{0,8,24},{0,9,144},{19,7,59}, {0,8,120},{0,8,56},{0,9,208},{17,7,17},{0,8,104},{0,8,40},{0,9,176}, {0,8,8},{0,8,136},{0,8,72},{0,9,240},{16,7,4},{0,8,84},{0,8,20}, {21,8,227},{19,7,43},{0,8,116},{0,8,52},{0,9,200},{17,7,13},{0,8,100}, {0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232},{16,7,8}, {0,8,92},{0,8,28},{0,9,152},{20,7,83},{0,8,124},{0,8,60},{0,9,216}, {18,7,23},{0,8,108},{0,8,44},{0,9,184},{0,8,12},{0,8,140},{0,8,76}, {0,9,248},{16,7,3},{0,8,82},{0,8,18},{21,8,163},{19,7,35},{0,8,114}, {0,8,50},{0,9,196},{17,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2}, {0,8,130},{0,8,66},{0,9,228},{16,7,7},{0,8,90},{0,8,26},{0,9,148}, {20,7,67},{0,8,122},{0,8,58},{0,9,212},{18,7,19},{0,8,106},{0,8,42}, {0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244},{16,7,5},{0,8,86}, {0,8,22},{64,8,0},{19,7,51},{0,8,118},{0,8,54},{0,9,204},{17,7,15}, {0,8,102},{0,8,38},{0,9,172},{0,8,6},{0,8,134},{0,8,70},{0,9,236}, {16,7,9},{0,8,94},{0,8,30},{0,9,156},{20,7,99},{0,8,126},{0,8,62}, {0,9,220},{18,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142}, {0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{21,8,131},{18,7,31}, {0,8,113},{0,8,49},{0,9,194},{16,7,10},{0,8,97},{0,8,33},{0,9,162}, {0,8,1},{0,8,129},{0,8,65},{0,9,226},{16,7,6},{0,8,89},{0,8,25}, {0,9,146},{19,7,59},{0,8,121},{0,8,57},{0,9,210},{17,7,17},{0,8,105}, {0,8,41},{0,9,178},{0,8,9},{0,8,137},{0,8,73},{0,9,242},{16,7,4}, {0,8,85},{0,8,21},{16,8,258},{19,7,43},{0,8,117},{0,8,53},{0,9,202}, {17,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133},{0,8,69}, {0,9,234},{16,7,8},{0,8,93},{0,8,29},{0,9,154},{20,7,83},{0,8,125}, {0,8,61},{0,9,218},{18,7,23},{0,8,109},{0,8,45},{0,9,186},{0,8,13}, {0,8,141},{0,8,77},{0,9,250},{16,7,3},{0,8,83},{0,8,19},{21,8,195}, {19,7,35},{0,8,115},{0,8,51},{0,9,198},{17,7,11},{0,8,99},{0,8,35}, {0,9,166},{0,8,3},{0,8,131},{0,8,67},{0,9,230},{16,7,7},{0,8,91}, {0,8,27},{0,9,150},{20,7,67},{0,8,123},{0,8,59},{0,9,214},{18,7,19}, {0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139},{0,8,75},{0,9,246}, {16,7,5},{0,8,87},{0,8,23},{64,8,0},{19,7,51},{0,8,119},{0,8,55}, {0,9,206},{17,7,15},{0,8,103},{0,8,39},{0,9,174},{0,8,7},{0,8,135}, {0,8,71},{0,9,238},{16,7,9},{0,8,95},{0,8,31},{0,9,158},{20,7,99}, {0,8,127},{0,8,63},{0,9,222},{18,7,27},{0,8,111},{0,8,47},{0,9,190}, {0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80},{0,8,16}, {20,8,115},{18,7,31},{0,8,112},{0,8,48},{0,9,193},{16,7,10},{0,8,96}, {0,8,32},{0,9,161},{0,8,0},{0,8,128},{0,8,64},{0,9,225},{16,7,6}, {0,8,88},{0,8,24},{0,9,145},{19,7,59},{0,8,120},{0,8,56},{0,9,209}, {17,7,17},{0,8,104},{0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72}, {0,9,241},{16,7,4},{0,8,84},{0,8,20},{21,8,227},{19,7,43},{0,8,116}, {0,8,52},{0,9,201},{17,7,13},{0,8,100},{0,8,36},{0,9,169},{0,8,4}, {0,8,132},{0,8,68},{0,9,233},{16,7,8},{0,8,92},{0,8,28},{0,9,153}, {20,7,83},{0,8,124},{0,8,60},{0,9,217},{18,7,23},{0,8,108},{0,8,44}, {0,9,185},{0,8,12},{0,8,140},{0,8,76},{0,9,249},{16,7,3},{0,8,82}, {0,8,18},{21,8,163},{19,7,35},{0,8,114},{0,8,50},{0,9,197},{17,7,11}, {0,8,98},{0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229}, {16,7,7},{0,8,90},{0,8,26},{0,9,149},{20,7,67},{0,8,122},{0,8,58}, {0,9,213},{18,7,19},{0,8,106},{0,8,42},{0,9,181},{0,8,10},{0,8,138}, {0,8,74},{0,9,245},{16,7,5},{0,8,86},{0,8,22},{64,8,0},{19,7,51}, {0,8,118},{0,8,54},{0,9,205},{17,7,15},{0,8,102},{0,8,38},{0,9,173}, {0,8,6},{0,8,134},{0,8,70},{0,9,237},{16,7,9},{0,8,94},{0,8,30}, {0,9,157},{20,7,99},{0,8,126},{0,8,62},{0,9,221},{18,7,27},{0,8,110}, {0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253},{96,7,0}, {0,8,81},{0,8,17},{21,8,131},{18,7,31},{0,8,113},{0,8,49},{0,9,195}, {16,7,10},{0,8,97},{0,8,33},{0,9,163},{0,8,1},{0,8,129},{0,8,65}, {0,9,227},{16,7,6},{0,8,89},{0,8,25},{0,9,147},{19,7,59},{0,8,121}, {0,8,57},{0,9,211},{17,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9}, {0,8,137},{0,8,73},{0,9,243},{16,7,4},{0,8,85},{0,8,21},{16,8,258}, {19,7,43},{0,8,117},{0,8,53},{0,9,203},{17,7,13},{0,8,101},{0,8,37}, {0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235},{16,7,8},{0,8,93}, {0,8,29},{0,9,155},{20,7,83},{0,8,125},{0,8,61},{0,9,219},{18,7,23}, {0,8,109},{0,8,45},{0,9,187},{0,8,13},{0,8,141},{0,8,77},{0,9,251}, {16,7,3},{0,8,83},{0,8,19},{21,8,195},{19,7,35},{0,8,115},{0,8,51}, {0,9,199},{17,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131}, {0,8,67},{0,9,231},{16,7,7},{0,8,91},{0,8,27},{0,9,151},{20,7,67}, {0,8,123},{0,8,59},{0,9,215},{18,7,19},{0,8,107},{0,8,43},{0,9,183}, {0,8,11},{0,8,139},{0,8,75},{0,9,247},{16,7,5},{0,8,87},{0,8,23}, {64,8,0},{19,7,51},{0,8,119},{0,8,55},{0,9,207},{17,7,15},{0,8,103}, {0,8,39},{0,9,175},{0,8,7},{0,8,135},{0,8,71},{0,9,239},{16,7,9}, {0,8,95},{0,8,31},{0,9,159},{20,7,99},{0,8,127},{0,8,63},{0,9,223}, {18,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143},{0,8,79}, {0,9,255} }; static const code distfix[32] = { {16,5,1},{23,5,257},{19,5,17},{27,5,4097},{17,5,5},{25,5,1025}, {21,5,65},{29,5,16385},{16,5,3},{24,5,513},{20,5,33},{28,5,8193}, {18,5,9},{26,5,2049},{22,5,129},{64,5,0},{16,5,2},{23,5,385}, {19,5,25},{27,5,6145},{17,5,7},{25,5,1537},{21,5,97},{29,5,24577}, {16,5,4},{24,5,769},{20,5,49},{28,5,12289},{18,5,13},{26,5,3073}, {22,5,193},{64,5,0} }; opengnb-ver1.6.0.a/libs/zlib/inflate.c000066400000000000000000001543371500454252100175740ustar00rootroot00000000000000/* inflate.c -- zlib decompression * Copyright (C) 1995-2022 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ /* * Change history: * * 1.2.beta0 24 Nov 2002 * - First version -- complete rewrite of inflate to simplify code, avoid * creation of window when not needed, minimize use of window when it is * needed, make inffast.c even faster, implement gzip decoding, and to * improve code readability and style over the previous zlib inflate code * * 1.2.beta1 25 Nov 2002 * - Use pointers for available input and output checking in inffast.c * - Remove input and output counters in inffast.c * - Change inffast.c entry and loop from avail_in >= 7 to >= 6 * - Remove unnecessary second byte pull from length extra in inffast.c * - Unroll direct copy to three copies per loop in inffast.c * * 1.2.beta2 4 Dec 2002 * - Change external routine names to reduce potential conflicts * - Correct filename to inffixed.h for fixed tables in inflate.c * - Make hbuf[] unsigned char to match parameter type in inflate.c * - Change strm->next_out[-state->offset] to *(strm->next_out - state->offset) * to avoid negation problem on Alphas (64 bit) in inflate.c * * 1.2.beta3 22 Dec 2002 * - Add comments on state->bits assertion in inffast.c * - Add comments on op field in inftrees.h * - Fix bug in reuse of allocated window after inflateReset() * - Remove bit fields--back to byte structure for speed * - Remove distance extra == 0 check in inflate_fast()--only helps for lengths * - Change post-increments to pre-increments in inflate_fast(), PPC biased? * - Add compile time option, POSTINC, to use post-increments instead (Intel?) * - Make MATCH copy in inflate() much faster for when inflate_fast() not used * - Use local copies of stream next and avail values, as well as local bit * buffer and bit count in inflate()--for speed when inflate_fast() not used * * 1.2.beta4 1 Jan 2003 * - Split ptr - 257 statements in inflate_table() to avoid compiler warnings * - Move a comment on output buffer sizes from inffast.c to inflate.c * - Add comments in inffast.c to introduce the inflate_fast() routine * - Rearrange window copies in inflate_fast() for speed and simplification * - Unroll last copy for window match in inflate_fast() * - Use local copies of window variables in inflate_fast() for speed * - Pull out common wnext == 0 case for speed in inflate_fast() * - Make op and len in inflate_fast() unsigned for consistency * - Add FAR to lcode and dcode declarations in inflate_fast() * - Simplified bad distance check in inflate_fast() * - Added inflateBackInit(), inflateBack(), and inflateBackEnd() in new * source file infback.c to provide a call-back interface to inflate for * programs like gzip and unzip -- uses window as output buffer to avoid * window copying * * 1.2.beta5 1 Jan 2003 * - Improved inflateBack() interface to allow the caller to provide initial * input in strm. * - Fixed stored blocks bug in inflateBack() * * 1.2.beta6 4 Jan 2003 * - Added comments in inffast.c on effectiveness of POSTINC * - Typecasting all around to reduce compiler warnings * - Changed loops from while (1) or do {} while (1) to for (;;), again to * make compilers happy * - Changed type of window in inflateBackInit() to unsigned char * * * 1.2.beta7 27 Jan 2003 * - Changed many types to unsigned or unsigned short to avoid warnings * - Added inflateCopy() function * * 1.2.0 9 Mar 2003 * - Changed inflateBack() interface to provide separate opaque descriptors * for the in() and out() functions * - Changed inflateBack() argument and in_func typedef to swap the length * and buffer address return values for the input function * - Check next_in and next_out for Z_NULL on entry to inflate() * * The history for versions after 1.2.0 are in ChangeLog in zlib distribution. */ #include "zutil.h" #include "inftrees.h" #include "inflate.h" #include "inffast.h" #ifdef MAKEFIXED # ifndef BUILDFIXED # define BUILDFIXED # endif #endif local int inflateStateCheck(z_streamp strm) { struct inflate_state FAR *state; if (strm == Z_NULL || strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0) return 1; state = (struct inflate_state FAR *)strm->state; if (state == Z_NULL || state->strm != strm || state->mode < HEAD || state->mode > SYNC) return 1; return 0; } int ZEXPORT inflateResetKeep(z_streamp strm) { struct inflate_state FAR *state; if (inflateStateCheck(strm)) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; strm->total_in = strm->total_out = state->total = 0; strm->msg = Z_NULL; if (state->wrap) /* to support ill-conceived Java test suite */ strm->adler = state->wrap & 1; state->mode = HEAD; state->last = 0; state->havedict = 0; state->flags = -1; state->dmax = 32768U; state->head = Z_NULL; state->hold = 0; state->bits = 0; state->lencode = state->distcode = state->next = state->codes; state->sane = 1; state->back = -1; Tracev((stderr, "inflate: reset\n")); return Z_OK; } int ZEXPORT inflateReset(z_streamp strm) { struct inflate_state FAR *state; if (inflateStateCheck(strm)) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; state->wsize = 0; state->whave = 0; state->wnext = 0; return inflateResetKeep(strm); } int ZEXPORT inflateReset2(z_streamp strm, int windowBits) { int wrap; struct inflate_state FAR *state; /* get the state */ if (inflateStateCheck(strm)) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; /* extract wrap request from windowBits parameter */ if (windowBits < 0) { if (windowBits < -15) return Z_STREAM_ERROR; wrap = 0; windowBits = -windowBits; } else { wrap = (windowBits >> 4) + 5; #ifdef GUNZIP if (windowBits < 48) windowBits &= 15; #endif } /* set number of window bits, free window if different */ if (windowBits && (windowBits < 8 || windowBits > 15)) return Z_STREAM_ERROR; if (state->window != Z_NULL && state->wbits != (unsigned)windowBits) { ZFREE(strm, state->window); state->window = Z_NULL; } /* update state and reset the rest of it */ state->wrap = wrap; state->wbits = (unsigned)windowBits; return inflateReset(strm); } int ZEXPORT inflateInit2_(z_streamp strm, int windowBits, const char *version, int stream_size) { int ret; struct inflate_state FAR *state; if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || stream_size != (int)(sizeof(z_stream))) return Z_VERSION_ERROR; if (strm == Z_NULL) return Z_STREAM_ERROR; strm->msg = Z_NULL; /* in case we return an error */ if (strm->zalloc == (alloc_func)0) { #ifdef Z_SOLO return Z_STREAM_ERROR; #else strm->zalloc = zcalloc; strm->opaque = (voidpf)0; #endif } if (strm->zfree == (free_func)0) #ifdef Z_SOLO return Z_STREAM_ERROR; #else strm->zfree = zcfree; #endif state = (struct inflate_state FAR *) ZALLOC(strm, 1, sizeof(struct inflate_state)); if (state == Z_NULL) return Z_MEM_ERROR; Tracev((stderr, "inflate: allocated\n")); strm->state = (struct internal_state FAR *)state; state->strm = strm; state->window = Z_NULL; state->mode = HEAD; /* to pass state test in inflateReset2() */ ret = inflateReset2(strm, windowBits); if (ret != Z_OK) { ZFREE(strm, state); strm->state = Z_NULL; } return ret; } int ZEXPORT inflateInit_(z_streamp strm, const char *version, int stream_size) { return inflateInit2_(strm, DEF_WBITS, version, stream_size); } int ZEXPORT inflatePrime(z_streamp strm, int bits, int value) { struct inflate_state FAR *state; if (inflateStateCheck(strm)) return Z_STREAM_ERROR; if (bits == 0) return Z_OK; state = (struct inflate_state FAR *)strm->state; if (bits < 0) { state->hold = 0; state->bits = 0; return Z_OK; } if (bits > 16 || state->bits + (uInt)bits > 32) return Z_STREAM_ERROR; value &= (1L << bits) - 1; state->hold += (unsigned)value << state->bits; state->bits += (uInt)bits; return Z_OK; } /* Return state with length and distance decoding tables and index sizes set to fixed code decoding. Normally this returns fixed tables from inffixed.h. If BUILDFIXED is defined, then instead this routine builds the tables the first time it's called, and returns those tables the first time and thereafter. This reduces the size of the code by about 2K bytes, in exchange for a little execution time. However, BUILDFIXED should not be used for threaded applications, since the rewriting of the tables and virgin may not be thread-safe. */ local void fixedtables(struct inflate_state FAR *state) { #ifdef BUILDFIXED static int virgin = 1; static code *lenfix, *distfix; static code fixed[544]; /* build fixed huffman tables if first call (may not be thread safe) */ if (virgin) { unsigned sym, bits; static code *next; /* literal/length table */ sym = 0; while (sym < 144) state->lens[sym++] = 8; while (sym < 256) state->lens[sym++] = 9; while (sym < 280) state->lens[sym++] = 7; while (sym < 288) state->lens[sym++] = 8; next = fixed; lenfix = next; bits = 9; inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work); /* distance table */ sym = 0; while (sym < 32) state->lens[sym++] = 5; distfix = next; bits = 5; inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work); /* do this just once */ virgin = 0; } #else /* !BUILDFIXED */ # include "inffixed.h" #endif /* BUILDFIXED */ state->lencode = lenfix; state->lenbits = 9; state->distcode = distfix; state->distbits = 5; } #ifdef MAKEFIXED #include /* Write out the inffixed.h that is #include'd above. Defining MAKEFIXED also defines BUILDFIXED, so the tables are built on the fly. makefixed() writes those tables to stdout, which would be piped to inffixed.h. A small program can simply call makefixed to do this: void makefixed(void); int main(void) { makefixed(); return 0; } Then that can be linked with zlib built with MAKEFIXED defined and run: a.out > inffixed.h */ void makefixed(void) { unsigned low, size; struct inflate_state state; fixedtables(&state); puts(" /* inffixed.h -- table for decoding fixed codes"); puts(" * Generated automatically by makefixed()."); puts(" */"); puts(""); puts(" /* WARNING: this file should *not* be used by applications."); puts(" It is part of the implementation of this library and is"); puts(" subject to change. Applications should only use zlib.h."); puts(" */"); puts(""); size = 1U << 9; printf(" static const code lenfix[%u] = {", size); low = 0; for (;;) { if ((low % 7) == 0) printf("\n "); printf("{%u,%u,%d}", (low & 127) == 99 ? 64 : state.lencode[low].op, state.lencode[low].bits, state.lencode[low].val); if (++low == size) break; putchar(','); } puts("\n };"); size = 1U << 5; printf("\n static const code distfix[%u] = {", size); low = 0; for (;;) { if ((low % 6) == 0) printf("\n "); printf("{%u,%u,%d}", state.distcode[low].op, state.distcode[low].bits, state.distcode[low].val); if (++low == size) break; putchar(','); } puts("\n };"); } #endif /* MAKEFIXED */ /* Update the window with the last wsize (normally 32K) bytes written before returning. If window does not exist yet, create it. This is only called when a window is already in use, or when output has been written during this inflate call, but the end of the deflate stream has not been reached yet. It is also called to create a window for dictionary data when a dictionary is loaded. Providing output buffers larger than 32K to inflate() should provide a speed advantage, since only the last 32K of output is copied to the sliding window upon return from inflate(), and since all distances after the first 32K of output will fall in the output data, making match copies simpler and faster. The advantage may be dependent on the size of the processor's data caches. */ local int updatewindow(z_streamp strm, const Bytef *end, unsigned copy) { struct inflate_state FAR *state; unsigned dist; state = (struct inflate_state FAR *)strm->state; /* if it hasn't been done already, allocate space for the window */ if (state->window == Z_NULL) { state->window = (unsigned char FAR *) ZALLOC(strm, 1U << state->wbits, sizeof(unsigned char)); if (state->window == Z_NULL) return 1; } /* if window not in use yet, initialize */ if (state->wsize == 0) { state->wsize = 1U << state->wbits; state->wnext = 0; state->whave = 0; } /* copy state->wsize or less output bytes into the circular window */ if (copy >= state->wsize) { zmemcpy(state->window, end - state->wsize, state->wsize); state->wnext = 0; state->whave = state->wsize; } else { dist = state->wsize - state->wnext; if (dist > copy) dist = copy; zmemcpy(state->window + state->wnext, end - copy, dist); copy -= dist; if (copy) { zmemcpy(state->window, end - copy, copy); state->wnext = copy; state->whave = state->wsize; } else { state->wnext += dist; if (state->wnext == state->wsize) state->wnext = 0; if (state->whave < state->wsize) state->whave += dist; } } return 0; } /* Macros for inflate(): */ /* check function to use adler32() for zlib or crc32() for gzip */ #ifdef GUNZIP # define UPDATE_CHECK(check, buf, len) \ (state->flags ? crc32(check, buf, len) : adler32(check, buf, len)) #else # define UPDATE_CHECK(check, buf, len) adler32(check, buf, len) #endif /* check macros for header crc */ #ifdef GUNZIP # define CRC2(check, word) \ do { \ hbuf[0] = (unsigned char)(word); \ hbuf[1] = (unsigned char)((word) >> 8); \ check = crc32(check, hbuf, 2); \ } while (0) # define CRC4(check, word) \ do { \ hbuf[0] = (unsigned char)(word); \ hbuf[1] = (unsigned char)((word) >> 8); \ hbuf[2] = (unsigned char)((word) >> 16); \ hbuf[3] = (unsigned char)((word) >> 24); \ check = crc32(check, hbuf, 4); \ } while (0) #endif /* Load registers with state in inflate() for speed */ #define LOAD() \ do { \ put = strm->next_out; \ left = strm->avail_out; \ next = strm->next_in; \ have = strm->avail_in; \ hold = state->hold; \ bits = state->bits; \ } while (0) /* Restore state from registers in inflate() */ #define RESTORE() \ do { \ strm->next_out = put; \ strm->avail_out = left; \ strm->next_in = next; \ strm->avail_in = have; \ state->hold = hold; \ state->bits = bits; \ } while (0) /* Clear the input bit accumulator */ #define INITBITS() \ do { \ hold = 0; \ bits = 0; \ } while (0) /* Get a byte of input into the bit accumulator, or return from inflate() if there is no input available. */ #define PULLBYTE() \ do { \ if (have == 0) goto inf_leave; \ have--; \ hold += (unsigned long)(*next++) << bits; \ bits += 8; \ } while (0) /* Assure that there are at least n bits in the bit accumulator. If there is not enough available input to do that, then return from inflate(). */ #define NEEDBITS(n) \ do { \ while (bits < (unsigned)(n)) \ PULLBYTE(); \ } while (0) /* Return the low n bits of the bit accumulator (n < 16) */ #define BITS(n) \ ((unsigned)hold & ((1U << (n)) - 1)) /* Remove n bits from the bit accumulator */ #define DROPBITS(n) \ do { \ hold >>= (n); \ bits -= (unsigned)(n); \ } while (0) /* Remove zero to seven bits as needed to go to a byte boundary */ #define BYTEBITS() \ do { \ hold >>= bits & 7; \ bits -= bits & 7; \ } while (0) /* inflate() uses a state machine to process as much input data and generate as much output data as possible before returning. The state machine is structured roughly as follows: for (;;) switch (state) { ... case STATEn: if (not enough input data or output space to make progress) return; ... make progress ... state = STATEm; break; ... } so when inflate() is called again, the same case is attempted again, and if the appropriate resources are provided, the machine proceeds to the next state. The NEEDBITS() macro is usually the way the state evaluates whether it can proceed or should return. NEEDBITS() does the return if the requested bits are not available. The typical use of the BITS macros is: NEEDBITS(n); ... do something with BITS(n) ... DROPBITS(n); where NEEDBITS(n) either returns from inflate() if there isn't enough input left to load n bits into the accumulator, or it continues. BITS(n) gives the low n bits in the accumulator. When done, DROPBITS(n) drops the low n bits off the accumulator. INITBITS() clears the accumulator and sets the number of available bits to zero. BYTEBITS() discards just enough bits to put the accumulator on a byte boundary. After BYTEBITS() and a NEEDBITS(8), then BITS(8) would return the next byte in the stream. NEEDBITS(n) uses PULLBYTE() to get an available byte of input, or to return if there is no input available. The decoding of variable length codes uses PULLBYTE() directly in order to pull just enough bytes to decode the next code, and no more. Some states loop until they get enough input, making sure that enough state information is maintained to continue the loop where it left off if NEEDBITS() returns in the loop. For example, want, need, and keep would all have to actually be part of the saved state in case NEEDBITS() returns: case STATEw: while (want < need) { NEEDBITS(n); keep[want++] = BITS(n); DROPBITS(n); } state = STATEx; case STATEx: As shown above, if the next state is also the next case, then the break is omitted. A state may also return if there is not enough output space available to complete that state. Those states are copying stored data, writing a literal byte, and copying a matching string. When returning, a "goto inf_leave" is used to update the total counters, update the check value, and determine whether any progress has been made during that inflate() call in order to return the proper return code. Progress is defined as a change in either strm->avail_in or strm->avail_out. When there is a window, goto inf_leave will update the window with the last output written. If a goto inf_leave occurs in the middle of decompression and there is no window currently, goto inf_leave will create one and copy output to the window for the next call of inflate(). In this implementation, the flush parameter of inflate() only affects the return code (per zlib.h). inflate() always writes as much as possible to strm->next_out, given the space available and the provided input--the effect documented in zlib.h of Z_SYNC_FLUSH. Furthermore, inflate() always defers the allocation of and copying into a sliding window until necessary, which provides the effect documented in zlib.h for Z_FINISH when the entire input stream available. So the only thing the flush parameter actually does is: when flush is set to Z_FINISH, inflate() cannot return Z_OK. Instead it will return Z_BUF_ERROR if it has not reached the end of the stream. */ int ZEXPORT inflate(z_streamp strm, int flush) { struct inflate_state FAR *state; z_const unsigned char FAR *next; /* next input */ unsigned char FAR *put; /* next output */ unsigned have, left; /* available input and output */ unsigned long hold; /* bit buffer */ unsigned bits; /* bits in bit buffer */ unsigned in, out; /* save starting available input and output */ unsigned copy; /* number of stored or match bytes to copy */ unsigned char FAR *from; /* where to copy match bytes from */ code here; /* current decoding table entry */ code last; /* parent table entry */ unsigned len; /* length to copy for repeats, bits to drop */ int ret; /* return code */ #ifdef GUNZIP unsigned char hbuf[4]; /* buffer for gzip header crc calculation */ #endif static const unsigned short order[19] = /* permutation of code lengths */ {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; if (inflateStateCheck(strm) || strm->next_out == Z_NULL || (strm->next_in == Z_NULL && strm->avail_in != 0)) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; if (state->mode == TYPE) state->mode = TYPEDO; /* skip check */ LOAD(); in = have; out = left; ret = Z_OK; for (;;) switch (state->mode) { case HEAD: if (state->wrap == 0) { state->mode = TYPEDO; break; } NEEDBITS(16); #ifdef GUNZIP if ((state->wrap & 2) && hold == 0x8b1f) { /* gzip header */ if (state->wbits == 0) state->wbits = 15; state->check = crc32(0L, Z_NULL, 0); CRC2(state->check, hold); INITBITS(); state->mode = FLAGS; break; } if (state->head != Z_NULL) state->head->done = -1; if (!(state->wrap & 1) || /* check if zlib header allowed */ #else if ( #endif ((BITS(8) << 8) + (hold >> 8)) % 31) { strm->msg = (char *)"incorrect header check"; state->mode = BAD; break; } if (BITS(4) != Z_DEFLATED) { strm->msg = (char *)"unknown compression method"; state->mode = BAD; break; } DROPBITS(4); len = BITS(4) + 8; if (state->wbits == 0) state->wbits = len; if (len > 15 || len > state->wbits) { strm->msg = (char *)"invalid window size"; state->mode = BAD; break; } state->dmax = 1U << len; state->flags = 0; /* indicate zlib header */ Tracev((stderr, "inflate: zlib header ok\n")); strm->adler = state->check = adler32(0L, Z_NULL, 0); state->mode = hold & 0x200 ? DICTID : TYPE; INITBITS(); break; #ifdef GUNZIP case FLAGS: NEEDBITS(16); state->flags = (int)(hold); if ((state->flags & 0xff) != Z_DEFLATED) { strm->msg = (char *)"unknown compression method"; state->mode = BAD; break; } if (state->flags & 0xe000) { strm->msg = (char *)"unknown header flags set"; state->mode = BAD; break; } if (state->head != Z_NULL) state->head->text = (int)((hold >> 8) & 1); if ((state->flags & 0x0200) && (state->wrap & 4)) CRC2(state->check, hold); INITBITS(); state->mode = TIME; /* fallthrough */ case TIME: NEEDBITS(32); if (state->head != Z_NULL) state->head->time = hold; if ((state->flags & 0x0200) && (state->wrap & 4)) CRC4(state->check, hold); INITBITS(); state->mode = OS; /* fallthrough */ case OS: NEEDBITS(16); if (state->head != Z_NULL) { state->head->xflags = (int)(hold & 0xff); state->head->os = (int)(hold >> 8); } if ((state->flags & 0x0200) && (state->wrap & 4)) CRC2(state->check, hold); INITBITS(); state->mode = EXLEN; /* fallthrough */ case EXLEN: if (state->flags & 0x0400) { NEEDBITS(16); state->length = (unsigned)(hold); if (state->head != Z_NULL) state->head->extra_len = (unsigned)hold; if ((state->flags & 0x0200) && (state->wrap & 4)) CRC2(state->check, hold); INITBITS(); } else if (state->head != Z_NULL) state->head->extra = Z_NULL; state->mode = EXTRA; /* fallthrough */ case EXTRA: if (state->flags & 0x0400) { copy = state->length; if (copy > have) copy = have; if (copy) { if (state->head != Z_NULL && state->head->extra != Z_NULL && (len = state->head->extra_len - state->length) < state->head->extra_max) { zmemcpy(state->head->extra + len, next, len + copy > state->head->extra_max ? state->head->extra_max - len : copy); } if ((state->flags & 0x0200) && (state->wrap & 4)) state->check = crc32(state->check, next, copy); have -= copy; next += copy; state->length -= copy; } if (state->length) goto inf_leave; } state->length = 0; state->mode = NAME; /* fallthrough */ case NAME: if (state->flags & 0x0800) { if (have == 0) goto inf_leave; copy = 0; do { len = (unsigned)(next[copy++]); if (state->head != Z_NULL && state->head->name != Z_NULL && state->length < state->head->name_max) state->head->name[state->length++] = (Bytef)len; } while (len && copy < have); if ((state->flags & 0x0200) && (state->wrap & 4)) state->check = crc32(state->check, next, copy); have -= copy; next += copy; if (len) goto inf_leave; } else if (state->head != Z_NULL) state->head->name = Z_NULL; state->length = 0; state->mode = COMMENT; /* fallthrough */ case COMMENT: if (state->flags & 0x1000) { if (have == 0) goto inf_leave; copy = 0; do { len = (unsigned)(next[copy++]); if (state->head != Z_NULL && state->head->comment != Z_NULL && state->length < state->head->comm_max) state->head->comment[state->length++] = (Bytef)len; } while (len && copy < have); if ((state->flags & 0x0200) && (state->wrap & 4)) state->check = crc32(state->check, next, copy); have -= copy; next += copy; if (len) goto inf_leave; } else if (state->head != Z_NULL) state->head->comment = Z_NULL; state->mode = HCRC; /* fallthrough */ case HCRC: if (state->flags & 0x0200) { NEEDBITS(16); if ((state->wrap & 4) && hold != (state->check & 0xffff)) { strm->msg = (char *)"header crc mismatch"; state->mode = BAD; break; } INITBITS(); } if (state->head != Z_NULL) { state->head->hcrc = (int)((state->flags >> 9) & 1); state->head->done = 1; } strm->adler = state->check = crc32(0L, Z_NULL, 0); state->mode = TYPE; break; #endif case DICTID: NEEDBITS(32); strm->adler = state->check = ZSWAP32(hold); INITBITS(); state->mode = DICT; /* fallthrough */ case DICT: if (state->havedict == 0) { RESTORE(); return Z_NEED_DICT; } strm->adler = state->check = adler32(0L, Z_NULL, 0); state->mode = TYPE; /* fallthrough */ case TYPE: if (flush == Z_BLOCK || flush == Z_TREES) goto inf_leave; /* fallthrough */ case TYPEDO: if (state->last) { BYTEBITS(); state->mode = CHECK; break; } NEEDBITS(3); state->last = BITS(1); DROPBITS(1); switch (BITS(2)) { case 0: /* stored block */ Tracev((stderr, "inflate: stored block%s\n", state->last ? " (last)" : "")); state->mode = STORED; break; case 1: /* fixed block */ fixedtables(state); Tracev((stderr, "inflate: fixed codes block%s\n", state->last ? " (last)" : "")); state->mode = LEN_; /* decode codes */ if (flush == Z_TREES) { DROPBITS(2); goto inf_leave; } break; case 2: /* dynamic block */ Tracev((stderr, "inflate: dynamic codes block%s\n", state->last ? " (last)" : "")); state->mode = TABLE; break; case 3: strm->msg = (char *)"invalid block type"; state->mode = BAD; } DROPBITS(2); break; case STORED: BYTEBITS(); /* go to byte boundary */ NEEDBITS(32); if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { strm->msg = (char *)"invalid stored block lengths"; state->mode = BAD; break; } state->length = (unsigned)hold & 0xffff; Tracev((stderr, "inflate: stored length %u\n", state->length)); INITBITS(); state->mode = COPY_; if (flush == Z_TREES) goto inf_leave; /* fallthrough */ case COPY_: state->mode = COPY; /* fallthrough */ case COPY: copy = state->length; if (copy) { if (copy > have) copy = have; if (copy > left) copy = left; if (copy == 0) goto inf_leave; zmemcpy(put, next, copy); have -= copy; next += copy; left -= copy; put += copy; state->length -= copy; break; } Tracev((stderr, "inflate: stored end\n")); state->mode = TYPE; break; case TABLE: NEEDBITS(14); state->nlen = BITS(5) + 257; DROPBITS(5); state->ndist = BITS(5) + 1; DROPBITS(5); state->ncode = BITS(4) + 4; DROPBITS(4); #ifndef PKZIP_BUG_WORKAROUND if (state->nlen > 286 || state->ndist > 30) { strm->msg = (char *)"too many length or distance symbols"; state->mode = BAD; break; } #endif Tracev((stderr, "inflate: table sizes ok\n")); state->have = 0; state->mode = LENLENS; /* fallthrough */ case LENLENS: while (state->have < state->ncode) { NEEDBITS(3); state->lens[order[state->have++]] = (unsigned short)BITS(3); DROPBITS(3); } while (state->have < 19) state->lens[order[state->have++]] = 0; state->next = state->codes; state->lencode = (const code FAR *)(state->next); state->lenbits = 7; ret = inflate_table(CODES, state->lens, 19, &(state->next), &(state->lenbits), state->work); if (ret) { strm->msg = (char *)"invalid code lengths set"; state->mode = BAD; break; } Tracev((stderr, "inflate: code lengths ok\n")); state->have = 0; state->mode = CODELENS; /* fallthrough */ case CODELENS: while (state->have < state->nlen + state->ndist) { for (;;) { here = state->lencode[BITS(state->lenbits)]; if ((unsigned)(here.bits) <= bits) break; PULLBYTE(); } if (here.val < 16) { DROPBITS(here.bits); state->lens[state->have++] = here.val; } else { if (here.val == 16) { NEEDBITS(here.bits + 2); DROPBITS(here.bits); if (state->have == 0) { strm->msg = (char *)"invalid bit length repeat"; state->mode = BAD; break; } len = state->lens[state->have - 1]; copy = 3 + BITS(2); DROPBITS(2); } else if (here.val == 17) { NEEDBITS(here.bits + 3); DROPBITS(here.bits); len = 0; copy = 3 + BITS(3); DROPBITS(3); } else { NEEDBITS(here.bits + 7); DROPBITS(here.bits); len = 0; copy = 11 + BITS(7); DROPBITS(7); } if (state->have + copy > state->nlen + state->ndist) { strm->msg = (char *)"invalid bit length repeat"; state->mode = BAD; break; } while (copy--) state->lens[state->have++] = (unsigned short)len; } } /* handle error breaks in while */ if (state->mode == BAD) break; /* check for end-of-block code (better have one) */ if (state->lens[256] == 0) { strm->msg = (char *)"invalid code -- missing end-of-block"; state->mode = BAD; break; } /* build code tables -- note: do not change the lenbits or distbits values here (9 and 6) without reading the comments in inftrees.h concerning the ENOUGH constants, which depend on those values */ state->next = state->codes; state->lencode = (const code FAR *)(state->next); state->lenbits = 9; ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), &(state->lenbits), state->work); if (ret) { strm->msg = (char *)"invalid literal/lengths set"; state->mode = BAD; break; } state->distcode = (const code FAR *)(state->next); state->distbits = 6; ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, &(state->next), &(state->distbits), state->work); if (ret) { strm->msg = (char *)"invalid distances set"; state->mode = BAD; break; } Tracev((stderr, "inflate: codes ok\n")); state->mode = LEN_; if (flush == Z_TREES) goto inf_leave; /* fallthrough */ case LEN_: state->mode = LEN; /* fallthrough */ case LEN: if (have >= 6 && left >= 258) { RESTORE(); inflate_fast(strm, out); LOAD(); if (state->mode == TYPE) state->back = -1; break; } state->back = 0; for (;;) { here = state->lencode[BITS(state->lenbits)]; if ((unsigned)(here.bits) <= bits) break; PULLBYTE(); } if (here.op && (here.op & 0xf0) == 0) { last = here; for (;;) { here = state->lencode[last.val + (BITS(last.bits + last.op) >> last.bits)]; if ((unsigned)(last.bits + here.bits) <= bits) break; PULLBYTE(); } DROPBITS(last.bits); state->back += last.bits; } DROPBITS(here.bits); state->back += here.bits; state->length = (unsigned)here.val; if ((int)(here.op) == 0) { Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? "inflate: literal '%c'\n" : "inflate: literal 0x%02x\n", here.val)); state->mode = LIT; break; } if (here.op & 32) { Tracevv((stderr, "inflate: end of block\n")); state->back = -1; state->mode = TYPE; break; } if (here.op & 64) { strm->msg = (char *)"invalid literal/length code"; state->mode = BAD; break; } state->extra = (unsigned)(here.op) & 15; state->mode = LENEXT; /* fallthrough */ case LENEXT: if (state->extra) { NEEDBITS(state->extra); state->length += BITS(state->extra); DROPBITS(state->extra); state->back += state->extra; } Tracevv((stderr, "inflate: length %u\n", state->length)); state->was = state->length; state->mode = DIST; /* fallthrough */ case DIST: for (;;) { here = state->distcode[BITS(state->distbits)]; if ((unsigned)(here.bits) <= bits) break; PULLBYTE(); } if ((here.op & 0xf0) == 0) { last = here; for (;;) { here = state->distcode[last.val + (BITS(last.bits + last.op) >> last.bits)]; if ((unsigned)(last.bits + here.bits) <= bits) break; PULLBYTE(); } DROPBITS(last.bits); state->back += last.bits; } DROPBITS(here.bits); state->back += here.bits; if (here.op & 64) { strm->msg = (char *)"invalid distance code"; state->mode = BAD; break; } state->offset = (unsigned)here.val; state->extra = (unsigned)(here.op) & 15; state->mode = DISTEXT; /* fallthrough */ case DISTEXT: if (state->extra) { NEEDBITS(state->extra); state->offset += BITS(state->extra); DROPBITS(state->extra); state->back += state->extra; } #ifdef INFLATE_STRICT if (state->offset > state->dmax) { strm->msg = (char *)"invalid distance too far back"; state->mode = BAD; break; } #endif Tracevv((stderr, "inflate: distance %u\n", state->offset)); state->mode = MATCH; /* fallthrough */ case MATCH: if (left == 0) goto inf_leave; copy = out - left; if (state->offset > copy) { /* copy from window */ copy = state->offset - copy; if (copy > state->whave) { if (state->sane) { strm->msg = (char *)"invalid distance too far back"; state->mode = BAD; break; } #ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR Trace((stderr, "inflate.c too far\n")); copy -= state->whave; if (copy > state->length) copy = state->length; if (copy > left) copy = left; left -= copy; state->length -= copy; do { *put++ = 0; } while (--copy); if (state->length == 0) state->mode = LEN; break; #endif } if (copy > state->wnext) { copy -= state->wnext; from = state->window + (state->wsize - copy); } else from = state->window + (state->wnext - copy); if (copy > state->length) copy = state->length; } else { /* copy from output */ from = put - state->offset; copy = state->length; } if (copy > left) copy = left; left -= copy; state->length -= copy; do { *put++ = *from++; } while (--copy); if (state->length == 0) state->mode = LEN; break; case LIT: if (left == 0) goto inf_leave; *put++ = (unsigned char)(state->length); left--; state->mode = LEN; break; case CHECK: if (state->wrap) { NEEDBITS(32); out -= left; strm->total_out += out; state->total += out; if ((state->wrap & 4) && out) strm->adler = state->check = UPDATE_CHECK(state->check, put - out, out); out = left; if ((state->wrap & 4) && ( #ifdef GUNZIP state->flags ? hold : #endif ZSWAP32(hold)) != state->check) { strm->msg = (char *)"incorrect data check"; state->mode = BAD; break; } INITBITS(); Tracev((stderr, "inflate: check matches trailer\n")); } #ifdef GUNZIP state->mode = LENGTH; /* fallthrough */ case LENGTH: if (state->wrap && state->flags) { NEEDBITS(32); if ((state->wrap & 4) && hold != (state->total & 0xffffffff)) { strm->msg = (char *)"incorrect length check"; state->mode = BAD; break; } INITBITS(); Tracev((stderr, "inflate: length matches trailer\n")); } #endif state->mode = DONE; /* fallthrough */ case DONE: ret = Z_STREAM_END; goto inf_leave; case BAD: ret = Z_DATA_ERROR; goto inf_leave; case MEM: return Z_MEM_ERROR; case SYNC: /* fallthrough */ default: return Z_STREAM_ERROR; } /* Return from inflate(), updating the total counts and the check value. If there was no progress during the inflate() call, return a buffer error. Call updatewindow() to create and/or update the window state. Note: a memory error from inflate() is non-recoverable. */ inf_leave: RESTORE(); if (state->wsize || (out != strm->avail_out && state->mode < BAD && (state->mode < CHECK || flush != Z_FINISH))) if (updatewindow(strm, strm->next_out, out - strm->avail_out)) { state->mode = MEM; return Z_MEM_ERROR; } in -= strm->avail_in; out -= strm->avail_out; strm->total_in += in; strm->total_out += out; state->total += out; if ((state->wrap & 4) && out) strm->adler = state->check = UPDATE_CHECK(state->check, strm->next_out - out, out); strm->data_type = (int)state->bits + (state->last ? 64 : 0) + (state->mode == TYPE ? 128 : 0) + (state->mode == LEN_ || state->mode == COPY_ ? 256 : 0); if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK) ret = Z_BUF_ERROR; return ret; } int ZEXPORT inflateEnd(z_streamp strm) { struct inflate_state FAR *state; if (inflateStateCheck(strm)) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; if (state->window != Z_NULL) ZFREE(strm, state->window); ZFREE(strm, strm->state); strm->state = Z_NULL; Tracev((stderr, "inflate: end\n")); return Z_OK; } int ZEXPORT inflateGetDictionary(z_streamp strm, Bytef *dictionary, uInt *dictLength) { struct inflate_state FAR *state; /* check state */ if (inflateStateCheck(strm)) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; /* copy dictionary */ if (state->whave && dictionary != Z_NULL) { zmemcpy(dictionary, state->window + state->wnext, state->whave - state->wnext); zmemcpy(dictionary + state->whave - state->wnext, state->window, state->wnext); } if (dictLength != Z_NULL) *dictLength = state->whave; return Z_OK; } int ZEXPORT inflateSetDictionary(z_streamp strm, const Bytef *dictionary, uInt dictLength) { struct inflate_state FAR *state; unsigned long dictid; int ret; /* check state */ if (inflateStateCheck(strm)) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; if (state->wrap != 0 && state->mode != DICT) return Z_STREAM_ERROR; /* check for correct dictionary identifier */ if (state->mode == DICT) { dictid = adler32(0L, Z_NULL, 0); dictid = adler32(dictid, dictionary, dictLength); if (dictid != state->check) return Z_DATA_ERROR; } /* copy dictionary to window using updatewindow(), which will amend the existing dictionary if appropriate */ ret = updatewindow(strm, dictionary + dictLength, dictLength); if (ret) { state->mode = MEM; return Z_MEM_ERROR; } state->havedict = 1; Tracev((stderr, "inflate: dictionary set\n")); return Z_OK; } int ZEXPORT inflateGetHeader(z_streamp strm, gz_headerp head) { struct inflate_state FAR *state; /* check state */ if (inflateStateCheck(strm)) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; if ((state->wrap & 2) == 0) return Z_STREAM_ERROR; /* save header structure */ state->head = head; head->done = 0; return Z_OK; } /* Search buf[0..len-1] for the pattern: 0, 0, 0xff, 0xff. Return when found or when out of input. When called, *have is the number of pattern bytes found in order so far, in 0..3. On return *have is updated to the new state. If on return *have equals four, then the pattern was found and the return value is how many bytes were read including the last byte of the pattern. If *have is less than four, then the pattern has not been found yet and the return value is len. In the latter case, syncsearch() can be called again with more data and the *have state. *have is initialized to zero for the first call. */ local unsigned syncsearch(unsigned FAR *have, const unsigned char FAR *buf, unsigned len) { unsigned got; unsigned next; got = *have; next = 0; while (next < len && got < 4) { if ((int)(buf[next]) == (got < 2 ? 0 : 0xff)) got++; else if (buf[next]) got = 0; else got = 4 - got; next++; } *have = got; return next; } int ZEXPORT inflateSync(z_streamp strm) { unsigned len; /* number of bytes to look at or looked at */ int flags; /* temporary to save header status */ unsigned long in, out; /* temporary to save total_in and total_out */ unsigned char buf[4]; /* to restore bit buffer to byte string */ struct inflate_state FAR *state; /* check parameters */ if (inflateStateCheck(strm)) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; if (strm->avail_in == 0 && state->bits < 8) return Z_BUF_ERROR; /* if first time, start search in bit buffer */ if (state->mode != SYNC) { state->mode = SYNC; state->hold >>= state->bits & 7; state->bits -= state->bits & 7; len = 0; while (state->bits >= 8) { buf[len++] = (unsigned char)(state->hold); state->hold >>= 8; state->bits -= 8; } state->have = 0; syncsearch(&(state->have), buf, len); } /* search available input */ len = syncsearch(&(state->have), strm->next_in, strm->avail_in); strm->avail_in -= len; strm->next_in += len; strm->total_in += len; /* return no joy or set up to restart inflate() on a new block */ if (state->have != 4) return Z_DATA_ERROR; if (state->flags == -1) state->wrap = 0; /* if no header yet, treat as raw */ else state->wrap &= ~4; /* no point in computing a check value now */ flags = state->flags; in = strm->total_in; out = strm->total_out; inflateReset(strm); strm->total_in = in; strm->total_out = out; state->flags = flags; state->mode = TYPE; return Z_OK; } /* Returns true if inflate is currently at the end of a block generated by Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP implementation to provide an additional safety check. PPP uses Z_SYNC_FLUSH but removes the length bytes of the resulting empty stored block. When decompressing, PPP checks that at the end of input packet, inflate is waiting for these length bytes. */ int ZEXPORT inflateSyncPoint(z_streamp strm) { struct inflate_state FAR *state; if (inflateStateCheck(strm)) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; return state->mode == STORED && state->bits == 0; } int ZEXPORT inflateCopy(z_streamp dest, z_streamp source) { struct inflate_state FAR *state; struct inflate_state FAR *copy; unsigned char FAR *window; unsigned wsize; /* check input */ if (inflateStateCheck(source) || dest == Z_NULL) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)source->state; /* allocate space */ copy = (struct inflate_state FAR *) ZALLOC(source, 1, sizeof(struct inflate_state)); if (copy == Z_NULL) return Z_MEM_ERROR; window = Z_NULL; if (state->window != Z_NULL) { window = (unsigned char FAR *) ZALLOC(source, 1U << state->wbits, sizeof(unsigned char)); if (window == Z_NULL) { ZFREE(source, copy); return Z_MEM_ERROR; } } /* copy state */ zmemcpy((voidpf)dest, (voidpf)source, sizeof(z_stream)); zmemcpy((voidpf)copy, (voidpf)state, sizeof(struct inflate_state)); copy->strm = dest; if (state->lencode >= state->codes && state->lencode <= state->codes + ENOUGH - 1) { copy->lencode = copy->codes + (state->lencode - state->codes); copy->distcode = copy->codes + (state->distcode - state->codes); } copy->next = copy->codes + (state->next - state->codes); if (window != Z_NULL) { wsize = 1U << state->wbits; zmemcpy(window, state->window, wsize); } copy->window = window; dest->state = (struct internal_state FAR *)copy; return Z_OK; } int ZEXPORT inflateUndermine(z_streamp strm, int subvert) { struct inflate_state FAR *state; if (inflateStateCheck(strm)) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; #ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR state->sane = !subvert; return Z_OK; #else (void)subvert; state->sane = 1; return Z_DATA_ERROR; #endif } int ZEXPORT inflateValidate(z_streamp strm, int check) { struct inflate_state FAR *state; if (inflateStateCheck(strm)) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; if (check && state->wrap) state->wrap |= 4; else state->wrap &= ~4; return Z_OK; } long ZEXPORT inflateMark(z_streamp strm) { struct inflate_state FAR *state; if (inflateStateCheck(strm)) return -(1L << 16); state = (struct inflate_state FAR *)strm->state; return (long)(((unsigned long)((long)state->back)) << 16) + (state->mode == COPY ? state->length : (state->mode == MATCH ? state->was - state->length : 0)); } unsigned long ZEXPORT inflateCodesUsed(z_streamp strm) { struct inflate_state FAR *state; if (inflateStateCheck(strm)) return (unsigned long)-1; state = (struct inflate_state FAR *)strm->state; return (unsigned long)(state->next - state->codes); } opengnb-ver1.6.0.a/libs/zlib/inflate.h000066400000000000000000000150331500454252100175660ustar00rootroot00000000000000/* inflate.h -- internal inflate state definition * Copyright (C) 1995-2019 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ /* WARNING: this file should *not* be used by applications. It is part of the implementation of the compression library and is subject to change. Applications should only use zlib.h. */ /* define NO_GZIP when compiling if you want to disable gzip header and trailer decoding by inflate(). NO_GZIP would be used to avoid linking in the crc code when it is not needed. For shared libraries, gzip decoding should be left enabled. */ #ifndef NO_GZIP # define GUNZIP #endif /* Possible inflate modes between inflate() calls */ typedef enum { HEAD = 16180, /* i: waiting for magic header */ FLAGS, /* i: waiting for method and flags (gzip) */ TIME, /* i: waiting for modification time (gzip) */ OS, /* i: waiting for extra flags and operating system (gzip) */ EXLEN, /* i: waiting for extra length (gzip) */ EXTRA, /* i: waiting for extra bytes (gzip) */ NAME, /* i: waiting for end of file name (gzip) */ COMMENT, /* i: waiting for end of comment (gzip) */ HCRC, /* i: waiting for header crc (gzip) */ DICTID, /* i: waiting for dictionary check value */ DICT, /* waiting for inflateSetDictionary() call */ TYPE, /* i: waiting for type bits, including last-flag bit */ TYPEDO, /* i: same, but skip check to exit inflate on new block */ STORED, /* i: waiting for stored size (length and complement) */ COPY_, /* i/o: same as COPY below, but only first time in */ COPY, /* i/o: waiting for input or output to copy stored block */ TABLE, /* i: waiting for dynamic block table lengths */ LENLENS, /* i: waiting for code length code lengths */ CODELENS, /* i: waiting for length/lit and distance code lengths */ LEN_, /* i: same as LEN below, but only first time in */ LEN, /* i: waiting for length/lit/eob code */ LENEXT, /* i: waiting for length extra bits */ DIST, /* i: waiting for distance code */ DISTEXT, /* i: waiting for distance extra bits */ MATCH, /* o: waiting for output space to copy string */ LIT, /* o: waiting for output space to write literal */ CHECK, /* i: waiting for 32-bit check value */ LENGTH, /* i: waiting for 32-bit length (gzip) */ DONE, /* finished check, done -- remain here until reset */ BAD, /* got a data error -- remain here until reset */ MEM, /* got an inflate() memory error -- remain here until reset */ SYNC /* looking for synchronization bytes to restart inflate() */ } inflate_mode; /* State transitions between above modes - (most modes can go to BAD or MEM on error -- not shown for clarity) Process header: HEAD -> (gzip) or (zlib) or (raw) (gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME -> COMMENT -> HCRC -> TYPE (zlib) -> DICTID or TYPE DICTID -> DICT -> TYPE (raw) -> TYPEDO Read deflate blocks: TYPE -> TYPEDO -> STORED or TABLE or LEN_ or CHECK STORED -> COPY_ -> COPY -> TYPE TABLE -> LENLENS -> CODELENS -> LEN_ LEN_ -> LEN Read deflate codes in fixed or dynamic block: LEN -> LENEXT or LIT or TYPE LENEXT -> DIST -> DISTEXT -> MATCH -> LEN LIT -> LEN Process trailer: CHECK -> LENGTH -> DONE */ /* State maintained between inflate() calls -- approximately 7K bytes, not including the allocated sliding window, which is up to 32K bytes. */ struct inflate_state { z_streamp strm; /* pointer back to this zlib stream */ inflate_mode mode; /* current inflate mode */ int last; /* true if processing last block */ int wrap; /* bit 0 true for zlib, bit 1 true for gzip, bit 2 true to validate check value */ int havedict; /* true if dictionary provided */ int flags; /* gzip header method and flags, 0 if zlib, or -1 if raw or no header yet */ unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */ unsigned long check; /* protected copy of check value */ unsigned long total; /* protected copy of output count */ gz_headerp head; /* where to save gzip header information */ /* sliding window */ unsigned wbits; /* log base 2 of requested window size */ unsigned wsize; /* window size or zero if not using window */ unsigned whave; /* valid bytes in the window */ unsigned wnext; /* window write index */ unsigned char FAR *window; /* allocated sliding window, if needed */ /* bit accumulator */ unsigned long hold; /* input bit accumulator */ unsigned bits; /* number of bits in "in" */ /* for string and stored block copying */ unsigned length; /* literal or length of data to copy */ unsigned offset; /* distance back to copy string from */ /* for table and code decoding */ unsigned extra; /* extra bits needed */ /* fixed and dynamic code tables */ code const FAR *lencode; /* starting table for length/literal codes */ code const FAR *distcode; /* starting table for distance codes */ unsigned lenbits; /* index bits for lencode */ unsigned distbits; /* index bits for distcode */ /* dynamic table building */ unsigned ncode; /* number of code length code lengths */ unsigned nlen; /* number of length code lengths */ unsigned ndist; /* number of distance code lengths */ unsigned have; /* number of code lengths in lens[] */ code FAR *next; /* next available space in codes[] */ unsigned short lens[320]; /* temporary storage for code lengths */ unsigned short work[288]; /* work area for code table building */ code codes[ENOUGH]; /* space for code tables */ int sane; /* if false, allow invalid distance too far */ int back; /* bits back of last unprocessed length/lit */ unsigned was; /* initial length of match */ }; opengnb-ver1.6.0.a/libs/zlib/inftrees.c000066400000000000000000000313401500454252100177550ustar00rootroot00000000000000/* inftrees.c -- generate Huffman trees for efficient decoding * Copyright (C) 1995-2024 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ #include "zutil.h" #include "inftrees.h" #define MAXBITS 15 const char inflate_copyright[] = " inflate 1.3.1 Copyright 1995-2024 Mark Adler "; /* If you use the zlib library in a product, an acknowledgment is welcome in the documentation of your product. If for some reason you cannot include such an acknowledgment, I would appreciate that you keep this copyright string in the executable of your product. */ /* Build a set of tables to decode the provided canonical Huffman code. The code lengths are lens[0..codes-1]. The result starts at *table, whose indices are 0..2^bits-1. work is a writable array of at least lens shorts, which is used as a work area. type is the type of code to be generated, CODES, LENS, or DISTS. On return, zero is success, -1 is an invalid code, and +1 means that ENOUGH isn't enough. table on return points to the next available entry's address. bits is the requested root table index bits, and on return it is the actual root table index bits. It will differ if the request is greater than the longest code or if it is less than the shortest code. */ int ZLIB_INTERNAL inflate_table(codetype type, unsigned short FAR *lens, unsigned codes, code FAR * FAR *table, unsigned FAR *bits, unsigned short FAR *work) { unsigned len; /* a code's length in bits */ unsigned sym; /* index of code symbols */ unsigned min, max; /* minimum and maximum code lengths */ unsigned root; /* number of index bits for root table */ unsigned curr; /* number of index bits for current table */ unsigned drop; /* code bits to drop for sub-table */ int left; /* number of prefix codes available */ unsigned used; /* code entries in table used */ unsigned huff; /* Huffman code */ unsigned incr; /* for incrementing code, index */ unsigned fill; /* index for replicating entries */ unsigned low; /* low bits for current root entry */ unsigned mask; /* mask for low root bits */ code here; /* table entry for duplication */ code FAR *next; /* next available space in table */ const unsigned short FAR *base; /* base value table to use */ const unsigned short FAR *extra; /* extra bits table to use */ unsigned match; /* use base and extra for symbol >= match */ unsigned short count[MAXBITS+1]; /* number of codes of each length */ unsigned short offs[MAXBITS+1]; /* offsets in table for each length */ static const unsigned short lbase[31] = { /* Length codes 257..285 base */ 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; static const unsigned short lext[31] = { /* Length codes 257..285 extra */ 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 203, 77}; static const unsigned short dbase[32] = { /* Distance codes 0..29 base */ 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577, 0, 0}; static const unsigned short dext[32] = { /* Distance codes 0..29 extra */ 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, 28, 28, 29, 29, 64, 64}; /* Process a set of code lengths to create a canonical Huffman code. The code lengths are lens[0..codes-1]. Each length corresponds to the symbols 0..codes-1. The Huffman code is generated by first sorting the symbols by length from short to long, and retaining the symbol order for codes with equal lengths. Then the code starts with all zero bits for the first code of the shortest length, and the codes are integer increments for the same length, and zeros are appended as the length increases. For the deflate format, these bits are stored backwards from their more natural integer increment ordering, and so when the decoding tables are built in the large loop below, the integer codes are incremented backwards. This routine assumes, but does not check, that all of the entries in lens[] are in the range 0..MAXBITS. The caller must assure this. 1..MAXBITS is interpreted as that code length. zero means that that symbol does not occur in this code. The codes are sorted by computing a count of codes for each length, creating from that a table of starting indices for each length in the sorted table, and then entering the symbols in order in the sorted table. The sorted table is work[], with that space being provided by the caller. The length counts are used for other purposes as well, i.e. finding the minimum and maximum length codes, determining if there are any codes at all, checking for a valid set of lengths, and looking ahead at length counts to determine sub-table sizes when building the decoding tables. */ /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */ for (len = 0; len <= MAXBITS; len++) count[len] = 0; for (sym = 0; sym < codes; sym++) count[lens[sym]]++; /* bound code lengths, force root to be within code lengths */ root = *bits; for (max = MAXBITS; max >= 1; max--) if (count[max] != 0) break; if (root > max) root = max; if (max == 0) { /* no symbols to code at all */ here.op = (unsigned char)64; /* invalid code marker */ here.bits = (unsigned char)1; here.val = (unsigned short)0; *(*table)++ = here; /* make a table to force an error */ *(*table)++ = here; *bits = 1; return 0; /* no symbols, but wait for decoding to report error */ } for (min = 1; min < max; min++) if (count[min] != 0) break; if (root < min) root = min; /* check for an over-subscribed or incomplete set of lengths */ left = 1; for (len = 1; len <= MAXBITS; len++) { left <<= 1; left -= count[len]; if (left < 0) return -1; /* over-subscribed */ } if (left > 0 && (type == CODES || max != 1)) return -1; /* incomplete set */ /* generate offsets into symbol table for each length for sorting */ offs[1] = 0; for (len = 1; len < MAXBITS; len++) offs[len + 1] = offs[len] + count[len]; /* sort symbols by length, by symbol order within each length */ for (sym = 0; sym < codes; sym++) if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym; /* Create and fill in decoding tables. In this loop, the table being filled is at next and has curr index bits. The code being used is huff with length len. That code is converted to an index by dropping drop bits off of the bottom. For codes where len is less than drop + curr, those top drop + curr - len bits are incremented through all values to fill the table with replicated entries. root is the number of index bits for the root table. When len exceeds root, sub-tables are created pointed to by the root entry with an index of the low root bits of huff. This is saved in low to check for when a new sub-table should be started. drop is zero when the root table is being filled, and drop is root when sub-tables are being filled. When a new sub-table is needed, it is necessary to look ahead in the code lengths to determine what size sub-table is needed. The length counts are used for this, and so count[] is decremented as codes are entered in the tables. used keeps track of how many table entries have been allocated from the provided *table space. It is checked for LENS and DIST tables against the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in the initial root table size constants. See the comments in inftrees.h for more information. sym increments through all symbols, and the loop terminates when all codes of length max, i.e. all codes, have been processed. This routine permits incomplete codes, so another loop after this one fills in the rest of the decoding tables with invalid code markers. */ /* set up for code type */ switch (type) { case CODES: base = extra = work; /* dummy value--not used */ match = 20; break; case LENS: base = lbase; extra = lext; match = 257; break; default: /* DISTS */ base = dbase; extra = dext; match = 0; } /* initialize state for loop */ huff = 0; /* starting code */ sym = 0; /* starting code symbol */ len = min; /* starting code length */ next = *table; /* current table to fill in */ curr = root; /* current table index bits */ drop = 0; /* current bits to drop from code for index */ low = (unsigned)(-1); /* trigger new sub-table when len > root */ used = 1U << root; /* use root table entries */ mask = used - 1; /* mask for comparing low */ /* check available table space */ if ((type == LENS && used > ENOUGH_LENS) || (type == DISTS && used > ENOUGH_DISTS)) return 1; /* process all codes and make table entries */ for (;;) { /* create table entry */ here.bits = (unsigned char)(len - drop); if (work[sym] + 1U < match) { here.op = (unsigned char)0; here.val = work[sym]; } else if (work[sym] >= match) { here.op = (unsigned char)(extra[work[sym] - match]); here.val = base[work[sym] - match]; } else { here.op = (unsigned char)(32 + 64); /* end of block */ here.val = 0; } /* replicate for those indices with low len bits equal to huff */ incr = 1U << (len - drop); fill = 1U << curr; min = fill; /* save offset to next table */ do { fill -= incr; next[(huff >> drop) + fill] = here; } while (fill != 0); /* backwards increment the len-bit code huff */ incr = 1U << (len - 1); while (huff & incr) incr >>= 1; if (incr != 0) { huff &= incr - 1; huff += incr; } else huff = 0; /* go to next symbol, update count, len */ sym++; if (--(count[len]) == 0) { if (len == max) break; len = lens[work[sym]]; } /* create new sub-table if needed */ if (len > root && (huff & mask) != low) { /* if first time, transition to sub-tables */ if (drop == 0) drop = root; /* increment past last table */ next += min; /* here min is 1 << curr */ /* determine length of next table */ curr = len - drop; left = (int)(1 << curr); while (curr + drop < max) { left -= count[curr + drop]; if (left <= 0) break; curr++; left <<= 1; } /* check for enough space */ used += 1U << curr; if ((type == LENS && used > ENOUGH_LENS) || (type == DISTS && used > ENOUGH_DISTS)) return 1; /* point entry in root table to sub-table */ low = huff & mask; (*table)[low].op = (unsigned char)curr; (*table)[low].bits = (unsigned char)root; (*table)[low].val = (unsigned short)(next - *table); } } /* fill in remaining table entry if code is incomplete (guaranteed to have at most one remaining entry, since if the code is incomplete, the maximum code length that was allowed to get this far is one bit) */ if (huff != 0) { here.op = (unsigned char)64; /* invalid code marker */ here.bits = (unsigned char)(len - drop); here.val = (unsigned short)0; next[huff] = here; } /* set return parameters */ *table += used; *bits = root; return 0; } opengnb-ver1.6.0.a/libs/zlib/inftrees.h000066400000000000000000000055501500454252100177660ustar00rootroot00000000000000/* inftrees.h -- header to use inftrees.c * Copyright (C) 1995-2005, 2010 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ /* WARNING: this file should *not* be used by applications. It is part of the implementation of the compression library and is subject to change. Applications should only use zlib.h. */ /* Structure for decoding tables. Each entry provides either the information needed to do the operation requested by the code that indexed that table entry, or it provides a pointer to another table that indexes more bits of the code. op indicates whether the entry is a pointer to another table, a literal, a length or distance, an end-of-block, or an invalid code. For a table pointer, the low four bits of op is the number of index bits of that table. For a length or distance, the low four bits of op is the number of extra bits to get after the code. bits is the number of bits in this code or part of the code to drop off of the bit buffer. val is the actual byte to output in the case of a literal, the base length or distance, or the offset from the current table to the next table. Each entry is four bytes. */ typedef struct { unsigned char op; /* operation, extra bits, table bits */ unsigned char bits; /* bits in this part of the code */ unsigned short val; /* offset in table or code value */ } code; /* op values as set by inflate_table(): 00000000 - literal 0000tttt - table link, tttt != 0 is the number of table index bits 0001eeee - length or distance, eeee is the number of extra bits 01100000 - end of block 01000000 - invalid code */ /* Maximum size of the dynamic table. The maximum number of code structures is 1444, which is the sum of 852 for literal/length codes and 592 for distance codes. These values were found by exhaustive searches using the program examples/enough.c found in the zlib distribution. The arguments to that program are the number of symbols, the initial root table size, and the maximum bit length of a code. "enough 286 9 15" for literal/length codes returns 852, and "enough 30 6 15" for distance codes returns 592. The initial root table size (9 or 6) is found in the fifth argument of the inflate_table() calls in inflate.c and infback.c. If the root table size is changed, then these maximum sizes would be need to be recalculated and updated. */ #define ENOUGH_LENS 852 #define ENOUGH_DISTS 592 #define ENOUGH (ENOUGH_LENS+ENOUGH_DISTS) /* Type of code to build for inflate_table() */ typedef enum { CODES, LENS, DISTS } codetype; int ZLIB_INTERNAL inflate_table(codetype type, unsigned short FAR *lens, unsigned codes, code FAR * FAR *table, unsigned FAR *bits, unsigned short FAR *work); opengnb-ver1.6.0.a/libs/zlib/trees.c000066400000000000000000001177511500454252100172730ustar00rootroot00000000000000/* trees.c -- output deflated data using Huffman coding * Copyright (C) 1995-2024 Jean-loup Gailly * detect_data_type() function provided freely by Cosmin Truta, 2006 * For conditions of distribution and use, see copyright notice in zlib.h */ /* * ALGORITHM * * The "deflation" process uses several Huffman trees. The more * common source values are represented by shorter bit sequences. * * Each code tree is stored in a compressed form which is itself * a Huffman encoding of the lengths of all the code strings (in * ascending order by source values). The actual code strings are * reconstructed from the lengths in the inflate process, as described * in the deflate specification. * * REFERENCES * * Deutsch, L.P.,"'Deflate' Compressed Data Format Specification". * Available in ftp.uu.net:/pub/archiving/zip/doc/deflate-1.1.doc * * Storer, James A. * Data Compression: Methods and Theory, pp. 49-50. * Computer Science Press, 1988. ISBN 0-7167-8156-5. * * Sedgewick, R. * Algorithms, p290. * Addison-Wesley, 1983. ISBN 0-201-06672-6. */ /* @(#) $Id$ */ /* #define GEN_TREES_H */ #include "deflate.h" #ifdef ZLIB_DEBUG # include #endif /* =========================================================================== * Constants */ #define MAX_BL_BITS 7 /* Bit length codes must not exceed MAX_BL_BITS bits */ #define END_BLOCK 256 /* end of block literal code */ #define REP_3_6 16 /* repeat previous bit length 3-6 times (2 bits of repeat count) */ #define REPZ_3_10 17 /* repeat a zero length 3-10 times (3 bits of repeat count) */ #define REPZ_11_138 18 /* repeat a zero length 11-138 times (7 bits of repeat count) */ local const int extra_lbits[LENGTH_CODES] /* extra bits for each length code */ = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0}; local const int extra_dbits[D_CODES] /* extra bits for each distance code */ = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; local const int extra_blbits[BL_CODES]/* extra bits for each bit length code */ = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7}; local const uch bl_order[BL_CODES] = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15}; /* The lengths of the bit length codes are sent in order of decreasing * probability, to avoid transmitting the lengths for unused bit length codes. */ /* =========================================================================== * Local data. These are initialized only once. */ #define DIST_CODE_LEN 512 /* see definition of array dist_code below */ #if defined(GEN_TREES_H) || !defined(STDC) /* non ANSI compilers may not accept trees.h */ local ct_data static_ltree[L_CODES+2]; /* The static literal tree. Since the bit lengths are imposed, there is no * need for the L_CODES extra codes used during heap construction. However * The codes 286 and 287 are needed to build a canonical tree (see _tr_init * below). */ local ct_data static_dtree[D_CODES]; /* The static distance tree. (Actually a trivial tree since all codes use * 5 bits.) */ uch _dist_code[DIST_CODE_LEN]; /* Distance codes. The first 256 values correspond to the distances * 3 .. 258, the last 256 values correspond to the top 8 bits of * the 15 bit distances. */ uch _length_code[MAX_MATCH-MIN_MATCH+1]; /* length code for each normalized match length (0 == MIN_MATCH) */ local int base_length[LENGTH_CODES]; /* First normalized length for each code (0 = MIN_MATCH) */ local int base_dist[D_CODES]; /* First normalized distance for each code (0 = distance of 1) */ #else # include "trees.h" #endif /* GEN_TREES_H */ struct static_tree_desc_s { const ct_data *static_tree; /* static tree or NULL */ const intf *extra_bits; /* extra bits for each code or NULL */ int extra_base; /* base index for extra_bits */ int elems; /* max number of elements in the tree */ int max_length; /* max bit length for the codes */ }; #ifdef NO_INIT_GLOBAL_POINTERS # define TCONST #else # define TCONST const #endif local TCONST static_tree_desc static_l_desc = {static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS}; local TCONST static_tree_desc static_d_desc = {static_dtree, extra_dbits, 0, D_CODES, MAX_BITS}; local TCONST static_tree_desc static_bl_desc = {(const ct_data *)0, extra_blbits, 0, BL_CODES, MAX_BL_BITS}; /* =========================================================================== * Output a short LSB first on the stream. * IN assertion: there is enough room in pendingBuf. */ #define put_short(s, w) { \ put_byte(s, (uch)((w) & 0xff)); \ put_byte(s, (uch)((ush)(w) >> 8)); \ } /* =========================================================================== * Reverse the first len bits of a code, using straightforward code (a faster * method would use a table) * IN assertion: 1 <= len <= 15 */ local unsigned bi_reverse(unsigned code, int len) { register unsigned res = 0; do { res |= code & 1; code >>= 1, res <<= 1; } while (--len > 0); return res >> 1; } /* =========================================================================== * Flush the bit buffer, keeping at most 7 bits in it. */ local void bi_flush(deflate_state *s) { if (s->bi_valid == 16) { put_short(s, s->bi_buf); s->bi_buf = 0; s->bi_valid = 0; } else if (s->bi_valid >= 8) { put_byte(s, (Byte)s->bi_buf); s->bi_buf >>= 8; s->bi_valid -= 8; } } /* =========================================================================== * Flush the bit buffer and align the output on a byte boundary */ local void bi_windup(deflate_state *s) { if (s->bi_valid > 8) { put_short(s, s->bi_buf); } else if (s->bi_valid > 0) { put_byte(s, (Byte)s->bi_buf); } s->bi_buf = 0; s->bi_valid = 0; #ifdef ZLIB_DEBUG s->bits_sent = (s->bits_sent + 7) & ~7; #endif } /* =========================================================================== * Generate the codes for a given tree and bit counts (which need not be * optimal). * IN assertion: the array bl_count contains the bit length statistics for * the given tree and the field len is set for all tree elements. * OUT assertion: the field code is set for all tree elements of non * zero code length. */ local void gen_codes(ct_data *tree, int max_code, ushf *bl_count) { ush next_code[MAX_BITS+1]; /* next code value for each bit length */ unsigned code = 0; /* running code value */ int bits; /* bit index */ int n; /* code index */ /* The distribution counts are first used to generate the code values * without bit reversal. */ for (bits = 1; bits <= MAX_BITS; bits++) { code = (code + bl_count[bits - 1]) << 1; next_code[bits] = (ush)code; } /* Check that the bit counts in bl_count are consistent. The last code * must be all ones. */ Assert (code + bl_count[MAX_BITS] - 1 == (1 << MAX_BITS) - 1, "inconsistent bit counts"); Tracev((stderr,"\ngen_codes: max_code %d ", max_code)); for (n = 0; n <= max_code; n++) { int len = tree[n].Len; if (len == 0) continue; /* Now reverse the bits */ tree[n].Code = (ush)bi_reverse(next_code[len]++, len); Tracecv(tree != static_ltree, (stderr,"\nn %3d %c l %2d c %4x (%x) ", n, (isgraph(n) ? n : ' '), len, tree[n].Code, next_code[len] - 1)); } } #ifdef GEN_TREES_H local void gen_trees_header(void); #endif #ifndef ZLIB_DEBUG # define send_code(s, c, tree) send_bits(s, tree[c].Code, tree[c].Len) /* Send a code of the given tree. c and tree must not have side effects */ #else /* !ZLIB_DEBUG */ # define send_code(s, c, tree) \ { if (z_verbose>2) fprintf(stderr,"\ncd %3d ",(c)); \ send_bits(s, tree[c].Code, tree[c].Len); } #endif /* =========================================================================== * Send a value on a given number of bits. * IN assertion: length <= 16 and value fits in length bits. */ #ifdef ZLIB_DEBUG local void send_bits(deflate_state *s, int value, int length) { Tracevv((stderr," l %2d v %4x ", length, value)); Assert(length > 0 && length <= 15, "invalid length"); s->bits_sent += (ulg)length; /* If not enough room in bi_buf, use (valid) bits from bi_buf and * (16 - bi_valid) bits from value, leaving (width - (16 - bi_valid)) * unused bits in value. */ if (s->bi_valid > (int)Buf_size - length) { s->bi_buf |= (ush)value << s->bi_valid; put_short(s, s->bi_buf); s->bi_buf = (ush)value >> (Buf_size - s->bi_valid); s->bi_valid += length - Buf_size; } else { s->bi_buf |= (ush)value << s->bi_valid; s->bi_valid += length; } } #else /* !ZLIB_DEBUG */ #define send_bits(s, value, length) \ { int len = length;\ if (s->bi_valid > (int)Buf_size - len) {\ int val = (int)value;\ s->bi_buf |= (ush)val << s->bi_valid;\ put_short(s, s->bi_buf);\ s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\ s->bi_valid += len - Buf_size;\ } else {\ s->bi_buf |= (ush)(value) << s->bi_valid;\ s->bi_valid += len;\ }\ } #endif /* ZLIB_DEBUG */ /* the arguments must not have side effects */ /* =========================================================================== * Initialize the various 'constant' tables. */ local void tr_static_init(void) { #if defined(GEN_TREES_H) || !defined(STDC) static int static_init_done = 0; int n; /* iterates over tree elements */ int bits; /* bit counter */ int length; /* length value */ int code; /* code value */ int dist; /* distance index */ ush bl_count[MAX_BITS+1]; /* number of codes at each bit length for an optimal tree */ if (static_init_done) return; /* For some embedded targets, global variables are not initialized: */ #ifdef NO_INIT_GLOBAL_POINTERS static_l_desc.static_tree = static_ltree; static_l_desc.extra_bits = extra_lbits; static_d_desc.static_tree = static_dtree; static_d_desc.extra_bits = extra_dbits; static_bl_desc.extra_bits = extra_blbits; #endif /* Initialize the mapping length (0..255) -> length code (0..28) */ length = 0; for (code = 0; code < LENGTH_CODES-1; code++) { base_length[code] = length; for (n = 0; n < (1 << extra_lbits[code]); n++) { _length_code[length++] = (uch)code; } } Assert (length == 256, "tr_static_init: length != 256"); /* Note that the length 255 (match length 258) can be represented * in two different ways: code 284 + 5 bits or code 285, so we * overwrite length_code[255] to use the best encoding: */ _length_code[length - 1] = (uch)code; /* Initialize the mapping dist (0..32K) -> dist code (0..29) */ dist = 0; for (code = 0 ; code < 16; code++) { base_dist[code] = dist; for (n = 0; n < (1 << extra_dbits[code]); n++) { _dist_code[dist++] = (uch)code; } } Assert (dist == 256, "tr_static_init: dist != 256"); dist >>= 7; /* from now on, all distances are divided by 128 */ for ( ; code < D_CODES; code++) { base_dist[code] = dist << 7; for (n = 0; n < (1 << (extra_dbits[code] - 7)); n++) { _dist_code[256 + dist++] = (uch)code; } } Assert (dist == 256, "tr_static_init: 256 + dist != 512"); /* Construct the codes of the static literal tree */ for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0; n = 0; while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++; while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++; while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++; while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++; /* Codes 286 and 287 do not exist, but we must include them in the * tree construction to get a canonical Huffman tree (longest code * all ones) */ gen_codes((ct_data *)static_ltree, L_CODES+1, bl_count); /* The static distance tree is trivial: */ for (n = 0; n < D_CODES; n++) { static_dtree[n].Len = 5; static_dtree[n].Code = bi_reverse((unsigned)n, 5); } static_init_done = 1; # ifdef GEN_TREES_H gen_trees_header(); # endif #endif /* defined(GEN_TREES_H) || !defined(STDC) */ } /* =========================================================================== * Generate the file trees.h describing the static trees. */ #ifdef GEN_TREES_H # ifndef ZLIB_DEBUG # include # endif # define SEPARATOR(i, last, width) \ ((i) == (last)? "\n};\n\n" : \ ((i) % (width) == (width) - 1 ? ",\n" : ", ")) void gen_trees_header(void) { FILE *header = fopen("trees.h", "w"); int i; Assert (header != NULL, "Can't open trees.h"); fprintf(header, "/* header created automatically with -DGEN_TREES_H */\n\n"); fprintf(header, "local const ct_data static_ltree[L_CODES+2] = {\n"); for (i = 0; i < L_CODES+2; i++) { fprintf(header, "{{%3u},{%3u}}%s", static_ltree[i].Code, static_ltree[i].Len, SEPARATOR(i, L_CODES+1, 5)); } fprintf(header, "local const ct_data static_dtree[D_CODES] = {\n"); for (i = 0; i < D_CODES; i++) { fprintf(header, "{{%2u},{%2u}}%s", static_dtree[i].Code, static_dtree[i].Len, SEPARATOR(i, D_CODES-1, 5)); } fprintf(header, "const uch ZLIB_INTERNAL _dist_code[DIST_CODE_LEN] = {\n"); for (i = 0; i < DIST_CODE_LEN; i++) { fprintf(header, "%2u%s", _dist_code[i], SEPARATOR(i, DIST_CODE_LEN-1, 20)); } fprintf(header, "const uch ZLIB_INTERNAL _length_code[MAX_MATCH-MIN_MATCH+1]= {\n"); for (i = 0; i < MAX_MATCH-MIN_MATCH+1; i++) { fprintf(header, "%2u%s", _length_code[i], SEPARATOR(i, MAX_MATCH-MIN_MATCH, 20)); } fprintf(header, "local const int base_length[LENGTH_CODES] = {\n"); for (i = 0; i < LENGTH_CODES; i++) { fprintf(header, "%1u%s", base_length[i], SEPARATOR(i, LENGTH_CODES-1, 20)); } fprintf(header, "local const int base_dist[D_CODES] = {\n"); for (i = 0; i < D_CODES; i++) { fprintf(header, "%5u%s", base_dist[i], SEPARATOR(i, D_CODES-1, 10)); } fclose(header); } #endif /* GEN_TREES_H */ /* =========================================================================== * Initialize a new block. */ local void init_block(deflate_state *s) { int n; /* iterates over tree elements */ /* Initialize the trees. */ for (n = 0; n < L_CODES; n++) s->dyn_ltree[n].Freq = 0; for (n = 0; n < D_CODES; n++) s->dyn_dtree[n].Freq = 0; for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0; s->dyn_ltree[END_BLOCK].Freq = 1; s->opt_len = s->static_len = 0L; s->sym_next = s->matches = 0; } /* =========================================================================== * Initialize the tree data structures for a new zlib stream. */ void ZLIB_INTERNAL _tr_init(deflate_state *s) { tr_static_init(); s->l_desc.dyn_tree = s->dyn_ltree; s->l_desc.stat_desc = &static_l_desc; s->d_desc.dyn_tree = s->dyn_dtree; s->d_desc.stat_desc = &static_d_desc; s->bl_desc.dyn_tree = s->bl_tree; s->bl_desc.stat_desc = &static_bl_desc; s->bi_buf = 0; s->bi_valid = 0; #ifdef ZLIB_DEBUG s->compressed_len = 0L; s->bits_sent = 0L; #endif /* Initialize the first block of the first file: */ init_block(s); } #define SMALLEST 1 /* Index within the heap array of least frequent node in the Huffman tree */ /* =========================================================================== * Remove the smallest element from the heap and recreate the heap with * one less element. Updates heap and heap_len. */ #define pqremove(s, tree, top) \ {\ top = s->heap[SMALLEST]; \ s->heap[SMALLEST] = s->heap[s->heap_len--]; \ pqdownheap(s, tree, SMALLEST); \ } /* =========================================================================== * Compares to subtrees, using the tree depth as tie breaker when * the subtrees have equal frequency. This minimizes the worst case length. */ #define smaller(tree, n, m, depth) \ (tree[n].Freq < tree[m].Freq || \ (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m])) /* =========================================================================== * Restore the heap property by moving down the tree starting at node k, * exchanging a node with the smallest of its two sons if necessary, stopping * when the heap property is re-established (each father smaller than its * two sons). */ local void pqdownheap(deflate_state *s, ct_data *tree, int k) { int v = s->heap[k]; int j = k << 1; /* left son of k */ while (j <= s->heap_len) { /* Set j to the smallest of the two sons: */ if (j < s->heap_len && smaller(tree, s->heap[j + 1], s->heap[j], s->depth)) { j++; } /* Exit if v is smaller than both sons */ if (smaller(tree, v, s->heap[j], s->depth)) break; /* Exchange v with the smallest son */ s->heap[k] = s->heap[j]; k = j; /* And continue down the tree, setting j to the left son of k */ j <<= 1; } s->heap[k] = v; } /* =========================================================================== * Compute the optimal bit lengths for a tree and update the total bit length * for the current block. * IN assertion: the fields freq and dad are set, heap[heap_max] and * above are the tree nodes sorted by increasing frequency. * OUT assertions: the field len is set to the optimal bit length, the * array bl_count contains the frequencies for each bit length. * The length opt_len is updated; static_len is also updated if stree is * not null. */ local void gen_bitlen(deflate_state *s, tree_desc *desc) { ct_data *tree = desc->dyn_tree; int max_code = desc->max_code; const ct_data *stree = desc->stat_desc->static_tree; const intf *extra = desc->stat_desc->extra_bits; int base = desc->stat_desc->extra_base; int max_length = desc->stat_desc->max_length; int h; /* heap index */ int n, m; /* iterate over the tree elements */ int bits; /* bit length */ int xbits; /* extra bits */ ush f; /* frequency */ int overflow = 0; /* number of elements with bit length too large */ for (bits = 0; bits <= MAX_BITS; bits++) s->bl_count[bits] = 0; /* In a first pass, compute the optimal bit lengths (which may * overflow in the case of the bit length tree). */ tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */ for (h = s->heap_max + 1; h < HEAP_SIZE; h++) { n = s->heap[h]; bits = tree[tree[n].Dad].Len + 1; if (bits > max_length) bits = max_length, overflow++; tree[n].Len = (ush)bits; /* We overwrite tree[n].Dad which is no longer needed */ if (n > max_code) continue; /* not a leaf node */ s->bl_count[bits]++; xbits = 0; if (n >= base) xbits = extra[n - base]; f = tree[n].Freq; s->opt_len += (ulg)f * (unsigned)(bits + xbits); if (stree) s->static_len += (ulg)f * (unsigned)(stree[n].Len + xbits); } if (overflow == 0) return; Tracev((stderr,"\nbit length overflow\n")); /* This happens for example on obj2 and pic of the Calgary corpus */ /* Find the first bit length which could increase: */ do { bits = max_length - 1; while (s->bl_count[bits] == 0) bits--; s->bl_count[bits]--; /* move one leaf down the tree */ s->bl_count[bits + 1] += 2; /* move one overflow item as its brother */ s->bl_count[max_length]--; /* The brother of the overflow item also moves one step up, * but this does not affect bl_count[max_length] */ overflow -= 2; } while (overflow > 0); /* Now recompute all bit lengths, scanning in increasing frequency. * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all * lengths instead of fixing only the wrong ones. This idea is taken * from 'ar' written by Haruhiko Okumura.) */ for (bits = max_length; bits != 0; bits--) { n = s->bl_count[bits]; while (n != 0) { m = s->heap[--h]; if (m > max_code) continue; if ((unsigned) tree[m].Len != (unsigned) bits) { Tracev((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits)); s->opt_len += ((ulg)bits - tree[m].Len) * tree[m].Freq; tree[m].Len = (ush)bits; } n--; } } } #ifdef DUMP_BL_TREE # include #endif /* =========================================================================== * Construct one Huffman tree and assigns the code bit strings and lengths. * Update the total bit length for the current block. * IN assertion: the field freq is set for all tree elements. * OUT assertions: the fields len and code are set to the optimal bit length * and corresponding code. The length opt_len is updated; static_len is * also updated if stree is not null. The field max_code is set. */ local void build_tree(deflate_state *s, tree_desc *desc) { ct_data *tree = desc->dyn_tree; const ct_data *stree = desc->stat_desc->static_tree; int elems = desc->stat_desc->elems; int n, m; /* iterate over heap elements */ int max_code = -1; /* largest code with non zero frequency */ int node; /* new node being created */ /* Construct the initial heap, with least frequent element in * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n + 1]. * heap[0] is not used. */ s->heap_len = 0, s->heap_max = HEAP_SIZE; for (n = 0; n < elems; n++) { if (tree[n].Freq != 0) { s->heap[++(s->heap_len)] = max_code = n; s->depth[n] = 0; } else { tree[n].Len = 0; } } /* The pkzip format requires that at least one distance code exists, * and that at least one bit should be sent even if there is only one * possible code. So to avoid special checks later on we force at least * two codes of non zero frequency. */ while (s->heap_len < 2) { node = s->heap[++(s->heap_len)] = (max_code < 2 ? ++max_code : 0); tree[node].Freq = 1; s->depth[node] = 0; s->opt_len--; if (stree) s->static_len -= stree[node].Len; /* node is 0 or 1 so it does not have extra bits */ } desc->max_code = max_code; /* The elements heap[heap_len/2 + 1 .. heap_len] are leaves of the tree, * establish sub-heaps of increasing lengths: */ for (n = s->heap_len/2; n >= 1; n--) pqdownheap(s, tree, n); /* Construct the Huffman tree by repeatedly combining the least two * frequent nodes. */ node = elems; /* next internal node of the tree */ do { pqremove(s, tree, n); /* n = node of least frequency */ m = s->heap[SMALLEST]; /* m = node of next least frequency */ s->heap[--(s->heap_max)] = n; /* keep the nodes sorted by frequency */ s->heap[--(s->heap_max)] = m; /* Create a new node father of n and m */ tree[node].Freq = tree[n].Freq + tree[m].Freq; s->depth[node] = (uch)((s->depth[n] >= s->depth[m] ? s->depth[n] : s->depth[m]) + 1); tree[n].Dad = tree[m].Dad = (ush)node; #ifdef DUMP_BL_TREE if (tree == s->bl_tree) { fprintf(stderr,"\nnode %d(%d), sons %d(%d) %d(%d)", node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq); } #endif /* and insert the new node in the heap */ s->heap[SMALLEST] = node++; pqdownheap(s, tree, SMALLEST); } while (s->heap_len >= 2); s->heap[--(s->heap_max)] = s->heap[SMALLEST]; /* At this point, the fields freq and dad are set. We can now * generate the bit lengths. */ gen_bitlen(s, (tree_desc *)desc); /* The field len is now set, we can generate the bit codes */ gen_codes ((ct_data *)tree, max_code, s->bl_count); } /* =========================================================================== * Scan a literal or distance tree to determine the frequencies of the codes * in the bit length tree. */ local void scan_tree(deflate_state *s, ct_data *tree, int max_code) { int n; /* iterates over all tree elements */ int prevlen = -1; /* last emitted length */ int curlen; /* length of current code */ int nextlen = tree[0].Len; /* length of next code */ int count = 0; /* repeat count of the current code */ int max_count = 7; /* max repeat count */ int min_count = 4; /* min repeat count */ if (nextlen == 0) max_count = 138, min_count = 3; tree[max_code + 1].Len = (ush)0xffff; /* guard */ for (n = 0; n <= max_code; n++) { curlen = nextlen; nextlen = tree[n + 1].Len; if (++count < max_count && curlen == nextlen) { continue; } else if (count < min_count) { s->bl_tree[curlen].Freq += count; } else if (curlen != 0) { if (curlen != prevlen) s->bl_tree[curlen].Freq++; s->bl_tree[REP_3_6].Freq++; } else if (count <= 10) { s->bl_tree[REPZ_3_10].Freq++; } else { s->bl_tree[REPZ_11_138].Freq++; } count = 0; prevlen = curlen; if (nextlen == 0) { max_count = 138, min_count = 3; } else if (curlen == nextlen) { max_count = 6, min_count = 3; } else { max_count = 7, min_count = 4; } } } /* =========================================================================== * Send a literal or distance tree in compressed form, using the codes in * bl_tree. */ local void send_tree(deflate_state *s, ct_data *tree, int max_code) { int n; /* iterates over all tree elements */ int prevlen = -1; /* last emitted length */ int curlen; /* length of current code */ int nextlen = tree[0].Len; /* length of next code */ int count = 0; /* repeat count of the current code */ int max_count = 7; /* max repeat count */ int min_count = 4; /* min repeat count */ /* tree[max_code + 1].Len = -1; */ /* guard already set */ if (nextlen == 0) max_count = 138, min_count = 3; for (n = 0; n <= max_code; n++) { curlen = nextlen; nextlen = tree[n + 1].Len; if (++count < max_count && curlen == nextlen) { continue; } else if (count < min_count) { do { send_code(s, curlen, s->bl_tree); } while (--count != 0); } else if (curlen != 0) { if (curlen != prevlen) { send_code(s, curlen, s->bl_tree); count--; } Assert(count >= 3 && count <= 6, " 3_6?"); send_code(s, REP_3_6, s->bl_tree); send_bits(s, count - 3, 2); } else if (count <= 10) { send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count - 3, 3); } else { send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count - 11, 7); } count = 0; prevlen = curlen; if (nextlen == 0) { max_count = 138, min_count = 3; } else if (curlen == nextlen) { max_count = 6, min_count = 3; } else { max_count = 7, min_count = 4; } } } /* =========================================================================== * Construct the Huffman tree for the bit lengths and return the index in * bl_order of the last bit length code to send. */ local int build_bl_tree(deflate_state *s) { int max_blindex; /* index of last bit length code of non zero freq */ /* Determine the bit length frequencies for literal and distance trees */ scan_tree(s, (ct_data *)s->dyn_ltree, s->l_desc.max_code); scan_tree(s, (ct_data *)s->dyn_dtree, s->d_desc.max_code); /* Build the bit length tree: */ build_tree(s, (tree_desc *)(&(s->bl_desc))); /* opt_len now includes the length of the tree representations, except the * lengths of the bit lengths codes and the 5 + 5 + 4 bits for the counts. */ /* Determine the number of bit length codes to send. The pkzip format * requires that at least 4 bit length codes be sent. (appnote.txt says * 3 but the actual value used is 4.) */ for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) { if (s->bl_tree[bl_order[max_blindex]].Len != 0) break; } /* Update opt_len to include the bit length tree and counts */ s->opt_len += 3*((ulg)max_blindex + 1) + 5 + 5 + 4; Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", s->opt_len, s->static_len)); return max_blindex; } /* =========================================================================== * Send the header for a block using dynamic Huffman trees: the counts, the * lengths of the bit length codes, the literal tree and the distance tree. * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. */ local void send_all_trees(deflate_state *s, int lcodes, int dcodes, int blcodes) { int rank; /* index in bl_order */ Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes"); Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES, "too many codes"); Tracev((stderr, "\nbl counts: ")); send_bits(s, lcodes - 257, 5); /* not +255 as stated in appnote.txt */ send_bits(s, dcodes - 1, 5); send_bits(s, blcodes - 4, 4); /* not -3 as stated in appnote.txt */ for (rank = 0; rank < blcodes; rank++) { Tracev((stderr, "\nbl code %2d ", bl_order[rank])); send_bits(s, s->bl_tree[bl_order[rank]].Len, 3); } Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent)); send_tree(s, (ct_data *)s->dyn_ltree, lcodes - 1); /* literal tree */ Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent)); send_tree(s, (ct_data *)s->dyn_dtree, dcodes - 1); /* distance tree */ Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent)); } /* =========================================================================== * Send a stored block */ void ZLIB_INTERNAL _tr_stored_block(deflate_state *s, charf *buf, ulg stored_len, int last) { send_bits(s, (STORED_BLOCK<<1) + last, 3); /* send block type */ bi_windup(s); /* align on byte boundary */ put_short(s, (ush)stored_len); put_short(s, (ush)~stored_len); if (stored_len) zmemcpy(s->pending_buf + s->pending, (Bytef *)buf, stored_len); s->pending += stored_len; #ifdef ZLIB_DEBUG s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L; s->compressed_len += (stored_len + 4) << 3; s->bits_sent += 2*16; s->bits_sent += stored_len << 3; #endif } /* =========================================================================== * Flush the bits in the bit buffer to pending output (leaves at most 7 bits) */ void ZLIB_INTERNAL _tr_flush_bits(deflate_state *s) { bi_flush(s); } /* =========================================================================== * Send one empty static block to give enough lookahead for inflate. * This takes 10 bits, of which 7 may remain in the bit buffer. */ void ZLIB_INTERNAL _tr_align(deflate_state *s) { send_bits(s, STATIC_TREES<<1, 3); send_code(s, END_BLOCK, static_ltree); #ifdef ZLIB_DEBUG s->compressed_len += 10L; /* 3 for block type, 7 for EOB */ #endif bi_flush(s); } /* =========================================================================== * Send the block data compressed using the given Huffman trees */ local void compress_block(deflate_state *s, const ct_data *ltree, const ct_data *dtree) { unsigned dist; /* distance of matched string */ int lc; /* match length or unmatched char (if dist == 0) */ unsigned sx = 0; /* running index in symbol buffers */ unsigned code; /* the code to send */ int extra; /* number of extra bits to send */ if (s->sym_next != 0) do { #ifdef LIT_MEM dist = s->d_buf[sx]; lc = s->l_buf[sx++]; #else dist = s->sym_buf[sx++] & 0xff; dist += (unsigned)(s->sym_buf[sx++] & 0xff) << 8; lc = s->sym_buf[sx++]; #endif if (dist == 0) { send_code(s, lc, ltree); /* send a literal byte */ Tracecv(isgraph(lc), (stderr," '%c' ", lc)); } else { /* Here, lc is the match length - MIN_MATCH */ code = _length_code[lc]; send_code(s, code + LITERALS + 1, ltree); /* send length code */ extra = extra_lbits[code]; if (extra != 0) { lc -= base_length[code]; send_bits(s, lc, extra); /* send the extra length bits */ } dist--; /* dist is now the match distance - 1 */ code = d_code(dist); Assert (code < D_CODES, "bad d_code"); send_code(s, code, dtree); /* send the distance code */ extra = extra_dbits[code]; if (extra != 0) { dist -= (unsigned)base_dist[code]; send_bits(s, dist, extra); /* send the extra distance bits */ } } /* literal or match pair ? */ /* Check for no overlay of pending_buf on needed symbols */ #ifdef LIT_MEM Assert(s->pending < 2 * (s->lit_bufsize + sx), "pendingBuf overflow"); #else Assert(s->pending < s->lit_bufsize + sx, "pendingBuf overflow"); #endif } while (sx < s->sym_next); send_code(s, END_BLOCK, ltree); } /* =========================================================================== * Check if the data type is TEXT or BINARY, using the following algorithm: * - TEXT if the two conditions below are satisfied: * a) There are no non-portable control characters belonging to the * "block list" (0..6, 14..25, 28..31). * b) There is at least one printable character belonging to the * "allow list" (9 {TAB}, 10 {LF}, 13 {CR}, 32..255). * - BINARY otherwise. * - The following partially-portable control characters form a * "gray list" that is ignored in this detection algorithm: * (7 {BEL}, 8 {BS}, 11 {VT}, 12 {FF}, 26 {SUB}, 27 {ESC}). * IN assertion: the fields Freq of dyn_ltree are set. */ local int detect_data_type(deflate_state *s) { /* block_mask is the bit mask of block-listed bytes * set bits 0..6, 14..25, and 28..31 * 0xf3ffc07f = binary 11110011111111111100000001111111 */ unsigned long block_mask = 0xf3ffc07fUL; int n; /* Check for non-textual ("block-listed") bytes. */ for (n = 0; n <= 31; n++, block_mask >>= 1) if ((block_mask & 1) && (s->dyn_ltree[n].Freq != 0)) return Z_BINARY; /* Check for textual ("allow-listed") bytes. */ if (s->dyn_ltree[9].Freq != 0 || s->dyn_ltree[10].Freq != 0 || s->dyn_ltree[13].Freq != 0) return Z_TEXT; for (n = 32; n < LITERALS; n++) if (s->dyn_ltree[n].Freq != 0) return Z_TEXT; /* There are no "block-listed" or "allow-listed" bytes: * this stream either is empty or has tolerated ("gray-listed") bytes only. */ return Z_BINARY; } /* =========================================================================== * Determine the best encoding for the current block: dynamic trees, static * trees or store, and write out the encoded block. */ void ZLIB_INTERNAL _tr_flush_block(deflate_state *s, charf *buf, ulg stored_len, int last) { ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */ int max_blindex = 0; /* index of last bit length code of non zero freq */ /* Build the Huffman trees unless a stored block is forced */ if (s->level > 0) { /* Check if the file is binary or text */ if (s->strm->data_type == Z_UNKNOWN) s->strm->data_type = detect_data_type(s); /* Construct the literal and distance trees */ build_tree(s, (tree_desc *)(&(s->l_desc))); Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len, s->static_len)); build_tree(s, (tree_desc *)(&(s->d_desc))); Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len, s->static_len)); /* At this point, opt_len and static_len are the total bit lengths of * the compressed block data, excluding the tree representations. */ /* Build the bit length tree for the above two trees, and get the index * in bl_order of the last bit length code to send. */ max_blindex = build_bl_tree(s); /* Determine the best encoding. Compute the block lengths in bytes. */ opt_lenb = (s->opt_len + 3 + 7) >> 3; static_lenb = (s->static_len + 3 + 7) >> 3; Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ", opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len, s->sym_next / 3)); #ifndef FORCE_STATIC if (static_lenb <= opt_lenb || s->strategy == Z_FIXED) #endif opt_lenb = static_lenb; } else { Assert(buf != (char*)0, "lost buf"); opt_lenb = static_lenb = stored_len + 5; /* force a stored block */ } #ifdef FORCE_STORED if (buf != (char*)0) { /* force stored block */ #else if (stored_len + 4 <= opt_lenb && buf != (char*)0) { /* 4: two words for the lengths */ #endif /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. * Otherwise we can't have processed more than WSIZE input bytes since * the last block flush, because compression would have been * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to * transform a block into a stored block. */ _tr_stored_block(s, buf, stored_len, last); } else if (static_lenb == opt_lenb) { send_bits(s, (STATIC_TREES<<1) + last, 3); compress_block(s, (const ct_data *)static_ltree, (const ct_data *)static_dtree); #ifdef ZLIB_DEBUG s->compressed_len += 3 + s->static_len; #endif } else { send_bits(s, (DYN_TREES<<1) + last, 3); send_all_trees(s, s->l_desc.max_code + 1, s->d_desc.max_code + 1, max_blindex + 1); compress_block(s, (const ct_data *)s->dyn_ltree, (const ct_data *)s->dyn_dtree); #ifdef ZLIB_DEBUG s->compressed_len += 3 + s->opt_len; #endif } Assert (s->compressed_len == s->bits_sent, "bad compressed size"); /* The above check is made mod 2^32, for files larger than 512 MB * and uLong implemented on 32 bits. */ init_block(s); if (last) { bi_windup(s); #ifdef ZLIB_DEBUG s->compressed_len += 7; /* align on byte boundary */ #endif } Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len >> 3, s->compressed_len - 7*last)); } /* =========================================================================== * Save the match info and tally the frequency counts. Return true if * the current block must be flushed. */ int ZLIB_INTERNAL _tr_tally(deflate_state *s, unsigned dist, unsigned lc) { #ifdef LIT_MEM s->d_buf[s->sym_next] = (ush)dist; s->l_buf[s->sym_next++] = (uch)lc; #else s->sym_buf[s->sym_next++] = (uch)dist; s->sym_buf[s->sym_next++] = (uch)(dist >> 8); s->sym_buf[s->sym_next++] = (uch)lc; #endif if (dist == 0) { /* lc is the unmatched char */ s->dyn_ltree[lc].Freq++; } else { s->matches++; /* Here, lc is the match length - MIN_MATCH */ dist--; /* dist = match distance - 1 */ Assert((ush)dist < (ush)MAX_DIST(s) && (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) && (ush)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match"); s->dyn_ltree[_length_code[lc] + LITERALS + 1].Freq++; s->dyn_dtree[d_code(dist)].Freq++; } return (s->sym_next == s->sym_end); } opengnb-ver1.6.0.a/libs/zlib/trees.h000066400000000000000000000204301500454252100172630ustar00rootroot00000000000000/* header created automatically with -DGEN_TREES_H */ local const ct_data static_ltree[L_CODES+2] = { {{ 12},{ 8}}, {{140},{ 8}}, {{ 76},{ 8}}, {{204},{ 8}}, {{ 44},{ 8}}, {{172},{ 8}}, {{108},{ 8}}, {{236},{ 8}}, {{ 28},{ 8}}, {{156},{ 8}}, {{ 92},{ 8}}, {{220},{ 8}}, {{ 60},{ 8}}, {{188},{ 8}}, {{124},{ 8}}, {{252},{ 8}}, {{ 2},{ 8}}, {{130},{ 8}}, {{ 66},{ 8}}, {{194},{ 8}}, {{ 34},{ 8}}, {{162},{ 8}}, {{ 98},{ 8}}, {{226},{ 8}}, {{ 18},{ 8}}, {{146},{ 8}}, {{ 82},{ 8}}, {{210},{ 8}}, {{ 50},{ 8}}, {{178},{ 8}}, {{114},{ 8}}, {{242},{ 8}}, {{ 10},{ 8}}, {{138},{ 8}}, {{ 74},{ 8}}, {{202},{ 8}}, {{ 42},{ 8}}, {{170},{ 8}}, {{106},{ 8}}, {{234},{ 8}}, {{ 26},{ 8}}, {{154},{ 8}}, {{ 90},{ 8}}, {{218},{ 8}}, {{ 58},{ 8}}, {{186},{ 8}}, {{122},{ 8}}, {{250},{ 8}}, {{ 6},{ 8}}, {{134},{ 8}}, {{ 70},{ 8}}, {{198},{ 8}}, {{ 38},{ 8}}, {{166},{ 8}}, {{102},{ 8}}, {{230},{ 8}}, {{ 22},{ 8}}, {{150},{ 8}}, {{ 86},{ 8}}, {{214},{ 8}}, {{ 54},{ 8}}, {{182},{ 8}}, {{118},{ 8}}, {{246},{ 8}}, {{ 14},{ 8}}, {{142},{ 8}}, {{ 78},{ 8}}, {{206},{ 8}}, {{ 46},{ 8}}, {{174},{ 8}}, {{110},{ 8}}, {{238},{ 8}}, {{ 30},{ 8}}, {{158},{ 8}}, {{ 94},{ 8}}, {{222},{ 8}}, {{ 62},{ 8}}, {{190},{ 8}}, {{126},{ 8}}, {{254},{ 8}}, {{ 1},{ 8}}, {{129},{ 8}}, {{ 65},{ 8}}, {{193},{ 8}}, {{ 33},{ 8}}, {{161},{ 8}}, {{ 97},{ 8}}, {{225},{ 8}}, {{ 17},{ 8}}, {{145},{ 8}}, {{ 81},{ 8}}, {{209},{ 8}}, {{ 49},{ 8}}, {{177},{ 8}}, {{113},{ 8}}, {{241},{ 8}}, {{ 9},{ 8}}, {{137},{ 8}}, {{ 73},{ 8}}, {{201},{ 8}}, {{ 41},{ 8}}, {{169},{ 8}}, {{105},{ 8}}, {{233},{ 8}}, {{ 25},{ 8}}, {{153},{ 8}}, {{ 89},{ 8}}, {{217},{ 8}}, {{ 57},{ 8}}, {{185},{ 8}}, {{121},{ 8}}, {{249},{ 8}}, {{ 5},{ 8}}, {{133},{ 8}}, {{ 69},{ 8}}, {{197},{ 8}}, {{ 37},{ 8}}, {{165},{ 8}}, {{101},{ 8}}, {{229},{ 8}}, {{ 21},{ 8}}, {{149},{ 8}}, {{ 85},{ 8}}, {{213},{ 8}}, {{ 53},{ 8}}, {{181},{ 8}}, {{117},{ 8}}, {{245},{ 8}}, {{ 13},{ 8}}, {{141},{ 8}}, {{ 77},{ 8}}, {{205},{ 8}}, {{ 45},{ 8}}, {{173},{ 8}}, {{109},{ 8}}, {{237},{ 8}}, {{ 29},{ 8}}, {{157},{ 8}}, {{ 93},{ 8}}, {{221},{ 8}}, {{ 61},{ 8}}, {{189},{ 8}}, {{125},{ 8}}, {{253},{ 8}}, {{ 19},{ 9}}, {{275},{ 9}}, {{147},{ 9}}, {{403},{ 9}}, {{ 83},{ 9}}, {{339},{ 9}}, {{211},{ 9}}, {{467},{ 9}}, {{ 51},{ 9}}, {{307},{ 9}}, {{179},{ 9}}, {{435},{ 9}}, {{115},{ 9}}, {{371},{ 9}}, {{243},{ 9}}, {{499},{ 9}}, {{ 11},{ 9}}, {{267},{ 9}}, {{139},{ 9}}, {{395},{ 9}}, {{ 75},{ 9}}, {{331},{ 9}}, {{203},{ 9}}, {{459},{ 9}}, {{ 43},{ 9}}, {{299},{ 9}}, {{171},{ 9}}, {{427},{ 9}}, {{107},{ 9}}, {{363},{ 9}}, {{235},{ 9}}, {{491},{ 9}}, {{ 27},{ 9}}, {{283},{ 9}}, {{155},{ 9}}, {{411},{ 9}}, {{ 91},{ 9}}, {{347},{ 9}}, {{219},{ 9}}, {{475},{ 9}}, {{ 59},{ 9}}, {{315},{ 9}}, {{187},{ 9}}, {{443},{ 9}}, {{123},{ 9}}, {{379},{ 9}}, {{251},{ 9}}, {{507},{ 9}}, {{ 7},{ 9}}, {{263},{ 9}}, {{135},{ 9}}, {{391},{ 9}}, {{ 71},{ 9}}, {{327},{ 9}}, {{199},{ 9}}, {{455},{ 9}}, {{ 39},{ 9}}, {{295},{ 9}}, {{167},{ 9}}, {{423},{ 9}}, {{103},{ 9}}, {{359},{ 9}}, {{231},{ 9}}, {{487},{ 9}}, {{ 23},{ 9}}, {{279},{ 9}}, {{151},{ 9}}, {{407},{ 9}}, {{ 87},{ 9}}, {{343},{ 9}}, {{215},{ 9}}, {{471},{ 9}}, {{ 55},{ 9}}, {{311},{ 9}}, {{183},{ 9}}, {{439},{ 9}}, {{119},{ 9}}, {{375},{ 9}}, {{247},{ 9}}, {{503},{ 9}}, {{ 15},{ 9}}, {{271},{ 9}}, {{143},{ 9}}, {{399},{ 9}}, {{ 79},{ 9}}, {{335},{ 9}}, {{207},{ 9}}, {{463},{ 9}}, {{ 47},{ 9}}, {{303},{ 9}}, {{175},{ 9}}, {{431},{ 9}}, {{111},{ 9}}, {{367},{ 9}}, {{239},{ 9}}, {{495},{ 9}}, {{ 31},{ 9}}, {{287},{ 9}}, {{159},{ 9}}, {{415},{ 9}}, {{ 95},{ 9}}, {{351},{ 9}}, {{223},{ 9}}, {{479},{ 9}}, {{ 63},{ 9}}, {{319},{ 9}}, {{191},{ 9}}, {{447},{ 9}}, {{127},{ 9}}, {{383},{ 9}}, {{255},{ 9}}, {{511},{ 9}}, {{ 0},{ 7}}, {{ 64},{ 7}}, {{ 32},{ 7}}, {{ 96},{ 7}}, {{ 16},{ 7}}, {{ 80},{ 7}}, {{ 48},{ 7}}, {{112},{ 7}}, {{ 8},{ 7}}, {{ 72},{ 7}}, {{ 40},{ 7}}, {{104},{ 7}}, {{ 24},{ 7}}, {{ 88},{ 7}}, {{ 56},{ 7}}, {{120},{ 7}}, {{ 4},{ 7}}, {{ 68},{ 7}}, {{ 36},{ 7}}, {{100},{ 7}}, {{ 20},{ 7}}, {{ 84},{ 7}}, {{ 52},{ 7}}, {{116},{ 7}}, {{ 3},{ 8}}, {{131},{ 8}}, {{ 67},{ 8}}, {{195},{ 8}}, {{ 35},{ 8}}, {{163},{ 8}}, {{ 99},{ 8}}, {{227},{ 8}} }; local const ct_data static_dtree[D_CODES] = { {{ 0},{ 5}}, {{16},{ 5}}, {{ 8},{ 5}}, {{24},{ 5}}, {{ 4},{ 5}}, {{20},{ 5}}, {{12},{ 5}}, {{28},{ 5}}, {{ 2},{ 5}}, {{18},{ 5}}, {{10},{ 5}}, {{26},{ 5}}, {{ 6},{ 5}}, {{22},{ 5}}, {{14},{ 5}}, {{30},{ 5}}, {{ 1},{ 5}}, {{17},{ 5}}, {{ 9},{ 5}}, {{25},{ 5}}, {{ 5},{ 5}}, {{21},{ 5}}, {{13},{ 5}}, {{29},{ 5}}, {{ 3},{ 5}}, {{19},{ 5}}, {{11},{ 5}}, {{27},{ 5}}, {{ 7},{ 5}}, {{23},{ 5}} }; const uch ZLIB_INTERNAL _dist_code[DIST_CODE_LEN] = { 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17, 18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29 }; const uch ZLIB_INTERNAL _length_code[MAX_MATCH-MIN_MATCH+1]= { 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, 19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28 }; local const int base_length[LENGTH_CODES] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 0 }; local const int base_dist[D_CODES] = { 0, 1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192, 256, 384, 512, 768, 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576 }; opengnb-ver1.6.0.a/libs/zlib/zconf.h000066400000000000000000000401641500454252100172660ustar00rootroot00000000000000/* zconf.h -- configuration of the zlib compression library * Copyright (C) 1995-2024 Jean-loup Gailly, Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ /* @(#) $Id$ */ #ifndef ZCONF_H #define ZCONF_H /* * If you *really* need a unique prefix for all types and library functions, * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. * Even better than compiling with -DZ_PREFIX would be to use configure to set * this permanently in zconf.h using "./configure --zprefix". */ #ifdef Z_PREFIX /* may be set to #if 1 by ./configure */ # define Z_PREFIX_SET /* all linked symbols and init macros */ # define _dist_code z__dist_code # define _length_code z__length_code # define _tr_align z__tr_align # define _tr_flush_bits z__tr_flush_bits # define _tr_flush_block z__tr_flush_block # define _tr_init z__tr_init # define _tr_stored_block z__tr_stored_block # define _tr_tally z__tr_tally # define adler32 z_adler32 # define adler32_combine z_adler32_combine # define adler32_combine64 z_adler32_combine64 # define adler32_z z_adler32_z # ifndef Z_SOLO # define compress z_compress # define compress2 z_compress2 # define compressBound z_compressBound # endif # define crc32 z_crc32 # define crc32_combine z_crc32_combine # define crc32_combine64 z_crc32_combine64 # define crc32_combine_gen z_crc32_combine_gen # define crc32_combine_gen64 z_crc32_combine_gen64 # define crc32_combine_op z_crc32_combine_op # define crc32_z z_crc32_z # define deflate z_deflate # define deflateBound z_deflateBound # define deflateCopy z_deflateCopy # define deflateEnd z_deflateEnd # define deflateGetDictionary z_deflateGetDictionary # define deflateInit z_deflateInit # define deflateInit2 z_deflateInit2 # define deflateInit2_ z_deflateInit2_ # define deflateInit_ z_deflateInit_ # define deflateParams z_deflateParams # define deflatePending z_deflatePending # define deflatePrime z_deflatePrime # define deflateReset z_deflateReset # define deflateResetKeep z_deflateResetKeep # define deflateSetDictionary z_deflateSetDictionary # define deflateSetHeader z_deflateSetHeader # define deflateTune z_deflateTune # define deflate_copyright z_deflate_copyright # define get_crc_table z_get_crc_table # ifndef Z_SOLO # define gz_error z_gz_error # define gz_intmax z_gz_intmax # define gz_strwinerror z_gz_strwinerror # define gzbuffer z_gzbuffer # define gzclearerr z_gzclearerr # define gzclose z_gzclose # define gzclose_r z_gzclose_r # define gzclose_w z_gzclose_w # define gzdirect z_gzdirect # define gzdopen z_gzdopen # define gzeof z_gzeof # define gzerror z_gzerror # define gzflush z_gzflush # define gzfread z_gzfread # define gzfwrite z_gzfwrite # define gzgetc z_gzgetc # define gzgetc_ z_gzgetc_ # define gzgets z_gzgets # define gzoffset z_gzoffset # define gzoffset64 z_gzoffset64 # define gzopen z_gzopen # define gzopen64 z_gzopen64 # ifdef _WIN32 # define gzopen_w z_gzopen_w # endif # define gzprintf z_gzprintf # define gzputc z_gzputc # define gzputs z_gzputs # define gzread z_gzread # define gzrewind z_gzrewind # define gzseek z_gzseek # define gzseek64 z_gzseek64 # define gzsetparams z_gzsetparams # define gztell z_gztell # define gztell64 z_gztell64 # define gzungetc z_gzungetc # define gzvprintf z_gzvprintf # define gzwrite z_gzwrite # endif # define inflate z_inflate # define inflateBack z_inflateBack # define inflateBackEnd z_inflateBackEnd # define inflateBackInit z_inflateBackInit # define inflateBackInit_ z_inflateBackInit_ # define inflateCodesUsed z_inflateCodesUsed # define inflateCopy z_inflateCopy # define inflateEnd z_inflateEnd # define inflateGetDictionary z_inflateGetDictionary # define inflateGetHeader z_inflateGetHeader # define inflateInit z_inflateInit # define inflateInit2 z_inflateInit2 # define inflateInit2_ z_inflateInit2_ # define inflateInit_ z_inflateInit_ # define inflateMark z_inflateMark # define inflatePrime z_inflatePrime # define inflateReset z_inflateReset # define inflateReset2 z_inflateReset2 # define inflateResetKeep z_inflateResetKeep # define inflateSetDictionary z_inflateSetDictionary # define inflateSync z_inflateSync # define inflateSyncPoint z_inflateSyncPoint # define inflateUndermine z_inflateUndermine # define inflateValidate z_inflateValidate # define inflate_copyright z_inflate_copyright # define inflate_fast z_inflate_fast # define inflate_table z_inflate_table # ifndef Z_SOLO # define uncompress z_uncompress # define uncompress2 z_uncompress2 # endif # define zError z_zError # ifndef Z_SOLO # define zcalloc z_zcalloc # define zcfree z_zcfree # endif # define zlibCompileFlags z_zlibCompileFlags # define zlibVersion z_zlibVersion /* all zlib typedefs in zlib.h and zconf.h */ # define Byte z_Byte # define Bytef z_Bytef # define alloc_func z_alloc_func # define charf z_charf # define free_func z_free_func # ifndef Z_SOLO # define gzFile z_gzFile # endif # define gz_header z_gz_header # define gz_headerp z_gz_headerp # define in_func z_in_func # define intf z_intf # define out_func z_out_func # define uInt z_uInt # define uIntf z_uIntf # define uLong z_uLong # define uLongf z_uLongf # define voidp z_voidp # define voidpc z_voidpc # define voidpf z_voidpf /* all zlib structs in zlib.h and zconf.h */ # define gz_header_s z_gz_header_s # define internal_state z_internal_state #endif #if defined(__MSDOS__) && !defined(MSDOS) # define MSDOS #endif #if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) # define OS2 #endif #if defined(_WINDOWS) && !defined(WINDOWS) # define WINDOWS #endif #if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__) # ifndef WIN32 # define WIN32 # endif #endif #if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) # if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) # ifndef SYS16BIT # define SYS16BIT # endif # endif #endif /* * Compile with -DMAXSEG_64K if the alloc function cannot allocate more * than 64k bytes at a time (needed on systems with 16-bit int). */ #ifdef SYS16BIT # define MAXSEG_64K #endif #ifdef MSDOS # define UNALIGNED_OK #endif #ifdef __STDC_VERSION__ # ifndef STDC # define STDC # endif # if __STDC_VERSION__ >= 199901L # ifndef STDC99 # define STDC99 # endif # endif #endif #if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) # define STDC #endif #if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) # define STDC #endif #if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) # define STDC #endif #if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) # define STDC #endif #if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ # define STDC #endif #ifndef STDC # ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ # define const /* note: need a more gentle solution here */ # endif #endif #if defined(ZLIB_CONST) && !defined(z_const) # define z_const const #else # define z_const #endif #ifdef Z_SOLO # ifdef _WIN64 typedef unsigned long long z_size_t; # else typedef unsigned long z_size_t; # endif #else # define z_longlong long long # if defined(NO_SIZE_T) typedef unsigned NO_SIZE_T z_size_t; # elif defined(STDC) # include typedef size_t z_size_t; # else typedef unsigned long z_size_t; # endif # undef z_longlong #endif /* Maximum value for memLevel in deflateInit2 */ #ifndef MAX_MEM_LEVEL # ifdef MAXSEG_64K # define MAX_MEM_LEVEL 8 # else # define MAX_MEM_LEVEL 9 # endif #endif /* Maximum value for windowBits in deflateInit2 and inflateInit2. * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files * created by gzip. (Files created by minigzip can still be extracted by * gzip.) */ #ifndef MAX_WBITS # define MAX_WBITS 15 /* 32K LZ77 window */ #endif /* The memory requirements for deflate are (in bytes): (1 << (windowBits+2)) + (1 << (memLevel+9)) that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) plus a few kilobytes for small objects. For example, if you want to reduce the default memory requirements from 256K to 128K, compile with make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" Of course this will generally degrade compression (there's no free lunch). The memory requirements for inflate are (in bytes) 1 << windowBits that is, 32K for windowBits=15 (default value) plus about 7 kilobytes for small objects. */ /* Type declarations */ #ifndef OF /* function prototypes */ # ifdef STDC # define OF(args) args # else # define OF(args) () # endif #endif /* The following definitions for FAR are needed only for MSDOS mixed * model programming (small or medium model with some far allocations). * This was tested only with MSC; for other MSDOS compilers you may have * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, * just define FAR to be empty. */ #ifdef SYS16BIT # if defined(M_I86SM) || defined(M_I86MM) /* MSC small or medium model */ # define SMALL_MEDIUM # ifdef _MSC_VER # define FAR _far # else # define FAR far # endif # endif # if (defined(__SMALL__) || defined(__MEDIUM__)) /* Turbo C small or medium model */ # define SMALL_MEDIUM # ifdef __BORLANDC__ # define FAR _far # else # define FAR far # endif # endif #endif #if defined(WINDOWS) || defined(WIN32) /* If building or using zlib as a DLL, define ZLIB_DLL. * This is not mandatory, but it offers a little performance increase. */ # ifdef ZLIB_DLL # if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) # ifdef ZLIB_INTERNAL # define ZEXTERN extern __declspec(dllexport) # else # define ZEXTERN extern __declspec(dllimport) # endif # endif # endif /* ZLIB_DLL */ /* If building or using zlib with the WINAPI/WINAPIV calling convention, * define ZLIB_WINAPI. * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. */ # ifdef ZLIB_WINAPI # ifdef FAR # undef FAR # endif # ifndef WIN32_LEAN_AND_MEAN # define WIN32_LEAN_AND_MEAN # endif # include /* No need for _export, use ZLIB.DEF instead. */ /* For complete Windows compatibility, use WINAPI, not __stdcall. */ # define ZEXPORT WINAPI # ifdef WIN32 # define ZEXPORTVA WINAPIV # else # define ZEXPORTVA FAR CDECL # endif # endif #endif #if defined (__BEOS__) # ifdef ZLIB_DLL # ifdef ZLIB_INTERNAL # define ZEXPORT __declspec(dllexport) # define ZEXPORTVA __declspec(dllexport) # else # define ZEXPORT __declspec(dllimport) # define ZEXPORTVA __declspec(dllimport) # endif # endif #endif #ifndef ZEXTERN # define ZEXTERN extern #endif #ifndef ZEXPORT # define ZEXPORT #endif #ifndef ZEXPORTVA # define ZEXPORTVA #endif #ifndef FAR # define FAR #endif #if !defined(__MACTYPES__) typedef unsigned char Byte; /* 8 bits */ #endif typedef unsigned int uInt; /* 16 bits or more */ typedef unsigned long uLong; /* 32 bits or more */ #ifdef SMALL_MEDIUM /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ # define Bytef Byte FAR #else typedef Byte FAR Bytef; #endif typedef char FAR charf; typedef int FAR intf; typedef uInt FAR uIntf; typedef uLong FAR uLongf; #ifdef STDC typedef void const *voidpc; typedef void FAR *voidpf; typedef void *voidp; #else typedef Byte const *voidpc; typedef Byte FAR *voidpf; typedef Byte *voidp; #endif #if !defined(Z_U4) && !defined(Z_SOLO) && defined(STDC) # include # if (UINT_MAX == 0xffffffffUL) # define Z_U4 unsigned # elif (ULONG_MAX == 0xffffffffUL) # define Z_U4 unsigned long # elif (USHRT_MAX == 0xffffffffUL) # define Z_U4 unsigned short # endif #endif #ifdef Z_U4 typedef Z_U4 z_crc_t; #else typedef unsigned long z_crc_t; #endif #ifdef HAVE_UNISTD_H /* may be set to #if 1 by ./configure */ # define Z_HAVE_UNISTD_H #endif #ifdef HAVE_STDARG_H /* may be set to #if 1 by ./configure */ # define Z_HAVE_STDARG_H #endif #ifdef STDC # ifndef Z_SOLO # include /* for off_t */ # endif #endif #if defined(STDC) || defined(Z_HAVE_STDARG_H) # ifndef Z_SOLO # include /* for va_list */ # endif #endif #ifdef _WIN32 # ifndef Z_SOLO # include /* for wchar_t */ # endif #endif /* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and * "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even * though the former does not conform to the LFS document), but considering * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as * equivalently requesting no 64-bit operations */ #if defined(_LARGEFILE64_SOURCE) && -_LARGEFILE64_SOURCE - -1 == 1 # undef _LARGEFILE64_SOURCE #endif #ifndef Z_HAVE_UNISTD_H # ifdef __WATCOMC__ # define Z_HAVE_UNISTD_H # endif #endif #ifndef Z_HAVE_UNISTD_H # if defined(_LARGEFILE64_SOURCE) && !defined(_WIN32) # define Z_HAVE_UNISTD_H # endif #endif #ifndef Z_SOLO # if defined(Z_HAVE_UNISTD_H) # include /* for SEEK_*, off_t, and _LFS64_LARGEFILE */ # ifdef VMS # include /* for off_t */ # endif # ifndef z_off_t # define z_off_t off_t # endif # endif #endif #if defined(_LFS64_LARGEFILE) && _LFS64_LARGEFILE-0 # define Z_LFS64 #endif #if defined(_LARGEFILE64_SOURCE) && defined(Z_LFS64) # define Z_LARGE64 #endif #if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS-0 == 64 && defined(Z_LFS64) # define Z_WANT64 #endif #if !defined(SEEK_SET) && !defined(Z_SOLO) # define SEEK_SET 0 /* Seek from beginning of file. */ # define SEEK_CUR 1 /* Seek from current position. */ # define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ #endif #ifndef z_off_t # define z_off_t long #endif #if !defined(_WIN32) && defined(Z_LARGE64) # define z_off64_t off64_t #else # if defined(_WIN32) && !defined(__GNUC__) # define z_off64_t __int64 # else # define z_off64_t z_off_t # endif #endif /* MVS linker does not support external names larger than 8 bytes */ #if defined(__MVS__) #pragma map(deflateInit_,"DEIN") #pragma map(deflateInit2_,"DEIN2") #pragma map(deflateEnd,"DEEND") #pragma map(deflateBound,"DEBND") #pragma map(inflateInit_,"ININ") #pragma map(inflateInit2_,"ININ2") #pragma map(inflateEnd,"INEND") #pragma map(inflateSync,"INSY") #pragma map(inflateSetDictionary,"INSEDI") #pragma map(compressBound,"CMBND") #pragma map(inflate_table,"INTABL") #pragma map(inflate_fast,"INFA") #pragma map(inflate_copyright,"INCOPY") #endif #endif /* ZCONF_H */ opengnb-ver1.6.0.a/libs/zlib/zlib.h000066400000000000000000002750751500454252100171220ustar00rootroot00000000000000/* zlib.h -- interface of the 'zlib' general purpose compression library version 1.3.1, January 22nd, 2024 Copyright (C) 1995-2024 Jean-loup Gailly and Mark Adler This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. Jean-loup Gailly Mark Adler jloup@gzip.org madler@alumni.caltech.edu The data format used by the zlib library is described by RFCs (Request for Comments) 1950 to 1952 in the files http://tools.ietf.org/html/rfc1950 (zlib format), rfc1951 (deflate format) and rfc1952 (gzip format). */ #ifndef ZLIB_H #define ZLIB_H #include "zconf.h" #ifdef __cplusplus extern "C" { #endif #define ZLIB_VERSION "1.3.1" #define ZLIB_VERNUM 0x1310 #define ZLIB_VER_MAJOR 1 #define ZLIB_VER_MINOR 3 #define ZLIB_VER_REVISION 1 #define ZLIB_VER_SUBREVISION 0 /* The 'zlib' compression library provides in-memory compression and decompression functions, including integrity checks of the uncompressed data. This version of the library supports only one compression method (deflation) but other algorithms will be added later and will have the same stream interface. Compression can be done in a single step if the buffers are large enough, or can be done by repeated calls of the compression function. In the latter case, the application must provide more input and/or consume the output (providing more output space) before each call. The compressed data format used by default by the in-memory functions is the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped around a deflate stream, which is itself documented in RFC 1951. The library also supports reading and writing files in gzip (.gz) format with an interface similar to that of stdio using the functions that start with "gz". The gzip format is different from the zlib format. gzip is a gzip wrapper, documented in RFC 1952, wrapped around a deflate stream. This library can optionally read and write gzip and raw deflate streams in memory as well. The zlib format was designed to be compact and fast for use in memory and on communications channels. The gzip format was designed for single- file compression on file systems, has a larger header than zlib to maintain directory information, and uses a different, slower check method than zlib. The library does not install any signal handler. The decoder checks the consistency of the compressed data, so the library should never crash even in the case of corrupted input. */ typedef voidpf (*alloc_func)(voidpf opaque, uInt items, uInt size); typedef void (*free_func)(voidpf opaque, voidpf address); struct internal_state; typedef struct z_stream_s { z_const Bytef *next_in; /* next input byte */ uInt avail_in; /* number of bytes available at next_in */ uLong total_in; /* total number of input bytes read so far */ Bytef *next_out; /* next output byte will go here */ uInt avail_out; /* remaining free space at next_out */ uLong total_out; /* total number of bytes output so far */ z_const char *msg; /* last error message, NULL if no error */ struct internal_state FAR *state; /* not visible by applications */ alloc_func zalloc; /* used to allocate the internal state */ free_func zfree; /* used to free the internal state */ voidpf opaque; /* private data object passed to zalloc and zfree */ int data_type; /* best guess about the data type: binary or text for deflate, or the decoding state for inflate */ uLong adler; /* Adler-32 or CRC-32 value of the uncompressed data */ uLong reserved; /* reserved for future use */ } z_stream; typedef z_stream FAR *z_streamp; /* gzip header information passed to and from zlib routines. See RFC 1952 for more details on the meanings of these fields. */ typedef struct gz_header_s { int text; /* true if compressed data believed to be text */ uLong time; /* modification time */ int xflags; /* extra flags (not used when writing a gzip file) */ int os; /* operating system */ Bytef *extra; /* pointer to extra field or Z_NULL if none */ uInt extra_len; /* extra field length (valid if extra != Z_NULL) */ uInt extra_max; /* space at extra (only when reading header) */ Bytef *name; /* pointer to zero-terminated file name or Z_NULL */ uInt name_max; /* space at name (only when reading header) */ Bytef *comment; /* pointer to zero-terminated comment or Z_NULL */ uInt comm_max; /* space at comment (only when reading header) */ int hcrc; /* true if there was or will be a header crc */ int done; /* true when done reading gzip header (not used when writing a gzip file) */ } gz_header; typedef gz_header FAR *gz_headerp; /* The application must update next_in and avail_in when avail_in has dropped to zero. It must update next_out and avail_out when avail_out has dropped to zero. The application must initialize zalloc, zfree and opaque before calling the init function. All other fields are set by the compression library and must not be updated by the application. The opaque value provided by the application will be passed as the first parameter for calls of zalloc and zfree. This can be useful for custom memory management. The compression library attaches no meaning to the opaque value. zalloc must return Z_NULL if there is not enough memory for the object. If zlib is used in a multi-threaded application, zalloc and zfree must be thread safe. In that case, zlib is thread-safe. When zalloc and zfree are Z_NULL on entry to the initialization function, they are set to internal routines that use the standard library functions malloc() and free(). On 16-bit systems, the functions zalloc and zfree must be able to allocate exactly 65536 bytes, but will not be required to allocate more than this if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, pointers returned by zalloc for objects of exactly 65536 bytes *must* have their offset normalized to zero. The default allocation function provided by this library ensures this (see zutil.c). To reduce memory requirements and avoid any allocation of 64K objects, at the expense of compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h). The fields total_in and total_out can be used for statistics or progress reports. After compression, total_in holds the total size of the uncompressed data and may be saved for use by the decompressor (particularly if the decompressor wants to decompress everything in a single step). */ /* constants */ #define Z_NO_FLUSH 0 #define Z_PARTIAL_FLUSH 1 #define Z_SYNC_FLUSH 2 #define Z_FULL_FLUSH 3 #define Z_FINISH 4 #define Z_BLOCK 5 #define Z_TREES 6 /* Allowed flush values; see deflate() and inflate() below for details */ #define Z_OK 0 #define Z_STREAM_END 1 #define Z_NEED_DICT 2 #define Z_ERRNO (-1) #define Z_STREAM_ERROR (-2) #define Z_DATA_ERROR (-3) #define Z_MEM_ERROR (-4) #define Z_BUF_ERROR (-5) #define Z_VERSION_ERROR (-6) /* Return codes for the compression/decompression functions. Negative values * are errors, positive values are used for special but normal events. */ #define Z_NO_COMPRESSION 0 #define Z_BEST_SPEED 1 #define Z_BEST_COMPRESSION 9 #define Z_DEFAULT_COMPRESSION (-1) /* compression levels */ #define Z_FILTERED 1 #define Z_HUFFMAN_ONLY 2 #define Z_RLE 3 #define Z_FIXED 4 #define Z_DEFAULT_STRATEGY 0 /* compression strategy; see deflateInit2() below for details */ #define Z_BINARY 0 #define Z_TEXT 1 #define Z_ASCII Z_TEXT /* for compatibility with 1.2.2 and earlier */ #define Z_UNKNOWN 2 /* Possible values of the data_type field for deflate() */ #define Z_DEFLATED 8 /* The deflate compression method (the only one supported in this version) */ #define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ #define zlib_version zlibVersion() /* for compatibility with versions < 1.0.2 */ /* basic functions */ ZEXTERN const char * ZEXPORT zlibVersion(void); /* The application can compare zlibVersion and ZLIB_VERSION for consistency. If the first character differs, the library code actually used is not compatible with the zlib.h header file used by the application. This check is automatically made by deflateInit and inflateInit. */ /* ZEXTERN int ZEXPORT deflateInit(z_streamp strm, int level); Initializes the internal stream state for compression. The fields zalloc, zfree and opaque must be initialized before by the caller. If zalloc and zfree are set to Z_NULL, deflateInit updates them to use default allocation functions. total_in, total_out, adler, and msg are initialized. The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: 1 gives best speed, 9 gives best compression, 0 gives no compression at all (the input data is simply copied a block at a time). Z_DEFAULT_COMPRESSION requests a default compromise between speed and compression (currently equivalent to level 6). deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_STREAM_ERROR if level is not a valid compression level, or Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible with the version assumed by the caller (ZLIB_VERSION). msg is set to null if there is no error message. deflateInit does not perform any compression: this will be done by deflate(). */ ZEXTERN int ZEXPORT deflate(z_streamp strm, int flush); /* deflate compresses as much data as possible, and stops when the input buffer becomes empty or the output buffer becomes full. It may introduce some output latency (reading input without producing any output) except when forced to flush. The detailed semantics are as follows. deflate performs one or both of the following actions: - Compress more input starting at next_in and update next_in and avail_in accordingly. If not all input can be processed (because there is not enough room in the output buffer), next_in and avail_in are updated and processing will resume at this point for the next call of deflate(). - Generate more output starting at next_out and update next_out and avail_out accordingly. This action is forced if the parameter flush is non zero. Forcing flush frequently degrades the compression ratio, so this parameter should be set only when necessary. Some output may be provided even if flush is zero. Before the call of deflate(), the application should ensure that at least one of the actions is possible, by providing more input and/or consuming more output, and updating avail_in or avail_out accordingly; avail_out should never be zero before the call. The application can consume the compressed output when it wants, for example when the output buffer is full (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK and with zero avail_out, it must be called again after making room in the output buffer because there might be more output pending. See deflatePending(), which can be used if desired to determine whether or not there is more output in that case. Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to decide how much data to accumulate before producing output, in order to maximize compression. If the parameter flush is set to Z_SYNC_FLUSH, all pending output is flushed to the output buffer and the output is aligned on a byte boundary, so that the decompressor can get all input data available so far. (In particular avail_in is zero after the call if enough output space has been provided before the call.) Flushing may degrade compression for some compression algorithms and so it should be used only when necessary. This completes the current deflate block and follows it with an empty stored block that is three bits plus filler bits to the next byte, followed by four bytes (00 00 ff ff). If flush is set to Z_PARTIAL_FLUSH, all pending output is flushed to the output buffer, but the output is not aligned to a byte boundary. All of the input data so far will be available to the decompressor, as for Z_SYNC_FLUSH. This completes the current deflate block and follows it with an empty fixed codes block that is 10 bits long. This assures that enough bytes are output in order for the decompressor to finish the block before the empty fixed codes block. If flush is set to Z_BLOCK, a deflate block is completed and emitted, as for Z_SYNC_FLUSH, but the output is not aligned on a byte boundary, and up to seven bits of the current block are held to be written as the next byte after the next deflate block is completed. In this case, the decompressor may not be provided enough bits at this point in order to complete decompression of the data provided so far to the compressor. It may need to wait for the next block to be emitted. This is for advanced applications that need to control the emission of deflate blocks. If flush is set to Z_FULL_FLUSH, all output is flushed as with Z_SYNC_FLUSH, and the compression state is reset so that decompression can restart from this point if previous compressed data has been damaged or if random access is desired. Using Z_FULL_FLUSH too often can seriously degrade compression. If deflate returns with avail_out == 0, this function must be called again with the same value of the flush parameter and more output space (updated avail_out), until the flush is complete (deflate returns with non-zero avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that avail_out is greater than six when the flush marker begins, in order to avoid repeated flush markers upon calling deflate() again when avail_out == 0. If the parameter flush is set to Z_FINISH, pending input is processed, pending output is flushed and deflate returns with Z_STREAM_END if there was enough output space. If deflate returns with Z_OK or Z_BUF_ERROR, this function must be called again with Z_FINISH and more output space (updated avail_out) but no more input data, until it returns with Z_STREAM_END or an error. After deflate has returned Z_STREAM_END, the only possible operations on the stream are deflateReset or deflateEnd. Z_FINISH can be used in the first deflate call after deflateInit if all the compression is to be done in a single step. In order to complete in one call, avail_out must be at least the value returned by deflateBound (see below). Then deflate is guaranteed to return Z_STREAM_END. If not enough output space is provided, deflate will not return Z_STREAM_END, and it must be called again as described above. deflate() sets strm->adler to the Adler-32 checksum of all input read so far (that is, total_in bytes). If a gzip stream is being generated, then strm->adler will be the CRC-32 checksum of the input read so far. (See deflateInit2 below.) deflate() may update strm->data_type if it can make a good guess about the input data type (Z_BINARY or Z_TEXT). If in doubt, the data is considered binary. This field is only for information purposes and does not affect the compression algorithm in any manner. deflate() returns Z_OK if some progress has been made (more input processed or more output produced), Z_STREAM_END if all input has been consumed and all output has been produced (only when flush is set to Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example if next_in or next_out was Z_NULL or the state was inadvertently written over by the application), or Z_BUF_ERROR if no progress is possible (for example avail_in or avail_out was zero). Note that Z_BUF_ERROR is not fatal, and deflate() can be called again with more input and more output space to continue compressing. */ ZEXTERN int ZEXPORT deflateEnd(z_streamp strm); /* All dynamically allocated data structures for this stream are freed. This function discards any unprocessed input and does not flush any pending output. deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state was inconsistent, Z_DATA_ERROR if the stream was freed prematurely (some input or output was discarded). In the error case, msg may be set but then points to a static string (which must not be deallocated). */ /* ZEXTERN int ZEXPORT inflateInit(z_streamp strm); Initializes the internal stream state for decompression. The fields next_in, avail_in, zalloc, zfree and opaque must be initialized before by the caller. In the current version of inflate, the provided input is not read or consumed. The allocation of a sliding window will be deferred to the first call of inflate (if the decompression does not complete on the first call). If zalloc and zfree are set to Z_NULL, inflateInit updates them to use default allocation functions. total_in, total_out, adler, and msg are initialized. inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_VERSION_ERROR if the zlib library version is incompatible with the version assumed by the caller, or Z_STREAM_ERROR if the parameters are invalid, such as a null pointer to the structure. msg is set to null if there is no error message. inflateInit does not perform any decompression. Actual decompression will be done by inflate(). So next_in, and avail_in, next_out, and avail_out are unused and unchanged. The current implementation of inflateInit() does not process any header information -- that is deferred until inflate() is called. */ ZEXTERN int ZEXPORT inflate(z_streamp strm, int flush); /* inflate decompresses as much data as possible, and stops when the input buffer becomes empty or the output buffer becomes full. It may introduce some output latency (reading input without producing any output) except when forced to flush. The detailed semantics are as follows. inflate performs one or both of the following actions: - Decompress more input starting at next_in and update next_in and avail_in accordingly. If not all input can be processed (because there is not enough room in the output buffer), then next_in and avail_in are updated accordingly, and processing will resume at this point for the next call of inflate(). - Generate more output starting at next_out and update next_out and avail_out accordingly. inflate() provides as much output as possible, until there is no more input data or no more space in the output buffer (see below about the flush parameter). Before the call of inflate(), the application should ensure that at least one of the actions is possible, by providing more input and/or consuming more output, and updating the next_* and avail_* values accordingly. If the caller of inflate() does not provide both available input and available output space, it is possible that there will be no progress made. The application can consume the uncompressed output when it wants, for example when the output buffer is full (avail_out == 0), or after each call of inflate(). If inflate returns Z_OK and with zero avail_out, it must be called again after making room in the output buffer because there might be more output pending. The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, Z_FINISH, Z_BLOCK, or Z_TREES. Z_SYNC_FLUSH requests that inflate() flush as much output as possible to the output buffer. Z_BLOCK requests that inflate() stop if and when it gets to the next deflate block boundary. When decoding the zlib or gzip format, this will cause inflate() to return immediately after the header and before the first block. When doing a raw inflate, inflate() will go ahead and process the first block, and will return when it gets to the end of that block, or when it runs out of data. The Z_BLOCK option assists in appending to or combining deflate streams. To assist in this, on return inflate() always sets strm->data_type to the number of unused bits in the last byte taken from strm->next_in, plus 64 if inflate() is currently decoding the last block in the deflate stream, plus 128 if inflate() returned immediately after decoding an end-of-block code or decoding the complete header up to just before the first byte of the deflate stream. The end-of-block will not be indicated until all of the uncompressed data from that block has been written to strm->next_out. The number of unused bits may in general be greater than seven, except when bit 7 of data_type is set, in which case the number of unused bits will be less than eight. data_type is set as noted here every time inflate() returns for all flush options, and so can be used to determine the amount of currently consumed input in bits. The Z_TREES option behaves as Z_BLOCK does, but it also returns when the end of each deflate block header is reached, before any actual data in that block is decoded. This allows the caller to determine the length of the deflate block header for later use in random access within a deflate block. 256 is added to the value of strm->data_type when inflate() returns immediately after reaching the end of the deflate block header. inflate() should normally be called until it returns Z_STREAM_END or an error. However if all decompression is to be performed in a single step (a single call of inflate), the parameter flush should be set to Z_FINISH. In this case all pending input is processed and all pending output is flushed; avail_out must be large enough to hold all of the uncompressed data for the operation to complete. (The size of the uncompressed data may have been saved by the compressor for this purpose.) The use of Z_FINISH is not required to perform an inflation in one step. However it may be used to inform inflate that a faster approach can be used for the single inflate() call. Z_FINISH also informs inflate to not maintain a sliding window if the stream completes, which reduces inflate's memory footprint. If the stream does not complete, either because not all of the stream is provided or not enough output space is provided, then a sliding window will be allocated and inflate() can be called again to continue the operation as if Z_NO_FLUSH had been used. In this implementation, inflate() always flushes as much output as possible to the output buffer, and always uses the faster approach on the first call. So the effects of the flush parameter in this implementation are on the return value of inflate() as noted below, when inflate() returns early when Z_BLOCK or Z_TREES is used, and when inflate() avoids the allocation of memory for a sliding window when Z_FINISH is used. If a preset dictionary is needed after this call (see inflateSetDictionary below), inflate sets strm->adler to the Adler-32 checksum of the dictionary chosen by the compressor and returns Z_NEED_DICT; otherwise it sets strm->adler to the Adler-32 checksum of all output produced so far (that is, total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described below. At the end of the stream, inflate() checks that its computed Adler-32 checksum is equal to that saved by the compressor and returns Z_STREAM_END only if the checksum is correct. inflate() can decompress and check either zlib-wrapped or gzip-wrapped deflate data. The header type is detected automatically, if requested when initializing with inflateInit2(). Any information contained in the gzip header is not retained unless inflateGetHeader() is used. When processing gzip-wrapped deflate data, strm->adler32 is set to the CRC-32 of the output produced so far. The CRC-32 is checked against the gzip trailer, as is the uncompressed length, modulo 2^32. inflate() returns Z_OK if some progress has been made (more input processed or more output produced), Z_STREAM_END if the end of the compressed data has been reached and all uncompressed output has been produced, Z_NEED_DICT if a preset dictionary is needed at this point, Z_DATA_ERROR if the input data was corrupted (input stream not conforming to the zlib format or incorrect check value, in which case strm->msg points to a string with a more specific error), Z_STREAM_ERROR if the stream structure was inconsistent (for example next_in or next_out was Z_NULL, or the state was inadvertently written over by the application), Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR if no progress was possible or if there was not enough room in the output buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and inflate() can be called again with more input and more output space to continue decompressing. If Z_DATA_ERROR is returned, the application may then call inflateSync() to look for a good compression block if a partial recovery of the data is to be attempted. */ ZEXTERN int ZEXPORT inflateEnd(z_streamp strm); /* All dynamically allocated data structures for this stream are freed. This function discards any unprocessed input and does not flush any pending output. inflateEnd returns Z_OK if success, or Z_STREAM_ERROR if the stream state was inconsistent. */ /* Advanced functions */ /* The following functions are needed only in some special applications. */ /* ZEXTERN int ZEXPORT deflateInit2(z_streamp strm, int level, int method, int windowBits, int memLevel, int strategy); This is another version of deflateInit with more compression options. The fields zalloc, zfree and opaque must be initialized before by the caller. The method parameter is the compression method. It must be Z_DEFLATED in this version of the library. The windowBits parameter is the base two logarithm of the window size (the size of the history buffer). It should be in the range 8..15 for this version of the library. Larger values of this parameter result in better compression at the expense of memory usage. The default value is 15 if deflateInit is used instead. For the current implementation of deflate(), a windowBits value of 8 (a window size of 256 bytes) is not supported. As a result, a request for 8 will result in 9 (a 512-byte window). In that case, providing 8 to inflateInit2() will result in an error when the zlib header with 9 is checked against the initialization of inflate(). The remedy is to not use 8 with deflateInit2() with this initialization, or at least in that case use 9 with inflateInit2(). windowBits can also be -8..-15 for raw deflate. In this case, -windowBits determines the window size. deflate() will then generate raw deflate data with no zlib header or trailer, and will not compute a check value. windowBits can also be greater than 15 for optional gzip encoding. Add 16 to windowBits to write a simple gzip header and trailer around the compressed data instead of a zlib wrapper. The gzip header will have no file name, no extra data, no comment, no modification time (set to zero), no header crc, and the operating system will be set to the appropriate value, if the operating system was determined at compile time. If a gzip stream is being written, strm->adler is a CRC-32 instead of an Adler-32. For raw deflate or gzip encoding, a request for a 256-byte window is rejected as invalid, since only the zlib header provides a means of transmitting the window size to the decompressor. The memLevel parameter specifies how much memory should be allocated for the internal compression state. memLevel=1 uses minimum memory but is slow and reduces compression ratio; memLevel=9 uses maximum memory for optimal speed. The default value is 8. See zconf.h for total memory usage as a function of windowBits and memLevel. The strategy parameter is used to tune the compression algorithm. Use the value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no string match), or Z_RLE to limit match distances to one (run-length encoding). Filtered data consists mostly of small values with a somewhat random distribution. In this case, the compression algorithm is tuned to compress them better. The effect of Z_FILTERED is to force more Huffman coding and less string matching; it is somewhat intermediate between Z_DEFAULT_STRATEGY and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as fast as Z_HUFFMAN_ONLY, but give better compression for PNG image data. The strategy parameter only affects the compression ratio but not the correctness of the compressed output even if it is not set appropriately. Z_FIXED prevents the use of dynamic Huffman codes, allowing for a simpler decoder for special applications. deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_STREAM_ERROR if any parameter is invalid (such as an invalid method), or Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible with the version assumed by the caller (ZLIB_VERSION). msg is set to null if there is no error message. deflateInit2 does not perform any compression: this will be done by deflate(). */ ZEXTERN int ZEXPORT deflateSetDictionary(z_streamp strm, const Bytef *dictionary, uInt dictLength); /* Initializes the compression dictionary from the given byte sequence without producing any compressed output. When using the zlib format, this function must be called immediately after deflateInit, deflateInit2 or deflateReset, and before any call of deflate. When doing raw deflate, this function must be called either before any call of deflate, or immediately after the completion of a deflate block, i.e. after all input has been consumed and all output has been delivered when using any of the flush options Z_BLOCK, Z_PARTIAL_FLUSH, Z_SYNC_FLUSH, or Z_FULL_FLUSH. The compressor and decompressor must use exactly the same dictionary (see inflateSetDictionary). The dictionary should consist of strings (byte sequences) that are likely to be encountered later in the data to be compressed, with the most commonly used strings preferably put towards the end of the dictionary. Using a dictionary is most useful when the data to be compressed is short and can be predicted with good accuracy; the data can then be compressed better than with the default empty dictionary. Depending on the size of the compression data structures selected by deflateInit or deflateInit2, a part of the dictionary may in effect be discarded, for example if the dictionary is larger than the window size provided in deflateInit or deflateInit2. Thus the strings most likely to be useful should be put at the end of the dictionary, not at the front. In addition, the current implementation of deflate will use at most the window size minus 262 bytes of the provided dictionary. Upon return of this function, strm->adler is set to the Adler-32 value of the dictionary; the decompressor may later use this value to determine which dictionary has been used by the compressor. (The Adler-32 value applies to the whole dictionary even if only a subset of the dictionary is actually used by the compressor.) If a raw deflate was requested, then the Adler-32 value is not computed and strm->adler is not set. deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is inconsistent (for example if deflate has already been called for this stream or if not at a block boundary for raw deflate). deflateSetDictionary does not perform any compression: this will be done by deflate(). */ ZEXTERN int ZEXPORT deflateGetDictionary(z_streamp strm, Bytef *dictionary, uInt *dictLength); /* Returns the sliding dictionary being maintained by deflate. dictLength is set to the number of bytes in the dictionary, and that many bytes are copied to dictionary. dictionary must have enough space, where 32768 bytes is always enough. If deflateGetDictionary() is called with dictionary equal to Z_NULL, then only the dictionary length is returned, and nothing is copied. Similarly, if dictLength is Z_NULL, then it is not set. deflateGetDictionary() may return a length less than the window size, even when more than the window size in input has been provided. It may return up to 258 bytes less in that case, due to how zlib's implementation of deflate manages the sliding window and lookahead for matches, where matches can be up to 258 bytes long. If the application needs the last window-size bytes of input, then that would need to be saved by the application outside of zlib. deflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the stream state is inconsistent. */ ZEXTERN int ZEXPORT deflateCopy(z_streamp dest, z_streamp source); /* Sets the destination stream as a complete copy of the source stream. This function can be useful when several compression strategies will be tried, for example when there are several ways of pre-processing the input data with a filter. The streams that will be discarded should then be freed by calling deflateEnd. Note that deflateCopy duplicates the internal compression state which can be quite large, so this strategy is slow and can consume lots of memory. deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_STREAM_ERROR if the source stream state was inconsistent (such as zalloc being Z_NULL). msg is left unchanged in both source and destination. */ ZEXTERN int ZEXPORT deflateReset(z_streamp strm); /* This function is equivalent to deflateEnd followed by deflateInit, but does not free and reallocate the internal compression state. The stream will leave the compression level and any other attributes that may have been set unchanged. total_in, total_out, adler, and msg are initialized. deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source stream state was inconsistent (such as zalloc or state being Z_NULL). */ ZEXTERN int ZEXPORT deflateParams(z_streamp strm, int level, int strategy); /* Dynamically update the compression level and compression strategy. The interpretation of level and strategy is as in deflateInit2(). This can be used to switch between compression and straight copy of the input data, or to switch to a different kind of input data requiring a different strategy. If the compression approach (which is a function of the level) or the strategy is changed, and if there have been any deflate() calls since the state was initialized or reset, then the input available so far is compressed with the old level and strategy using deflate(strm, Z_BLOCK). There are three approaches for the compression levels 0, 1..3, and 4..9 respectively. The new level and strategy will take effect at the next call of deflate(). If a deflate(strm, Z_BLOCK) is performed by deflateParams(), and it does not have enough output space to complete, then the parameter change will not take effect. In this case, deflateParams() can be called again with the same parameters and more output space to try again. In order to assure a change in the parameters on the first try, the deflate stream should be flushed using deflate() with Z_BLOCK or other flush request until strm.avail_out is not zero, before calling deflateParams(). Then no more input data should be provided before the deflateParams() call. If this is done, the old level and strategy will be applied to the data compressed before deflateParams(), and the new level and strategy will be applied to the data compressed after deflateParams(). deflateParams returns Z_OK on success, Z_STREAM_ERROR if the source stream state was inconsistent or if a parameter was invalid, or Z_BUF_ERROR if there was not enough output space to complete the compression of the available input data before a change in the strategy or approach. Note that in the case of a Z_BUF_ERROR, the parameters are not changed. A return value of Z_BUF_ERROR is not fatal, in which case deflateParams() can be retried with more output space. */ ZEXTERN int ZEXPORT deflateTune(z_streamp strm, int good_length, int max_lazy, int nice_length, int max_chain); /* Fine tune deflate's internal compression parameters. This should only be used by someone who understands the algorithm used by zlib's deflate for searching for the best matching string, and even then only by the most fanatic optimizer trying to squeeze out the last compressed bit for their specific input data. Read the deflate.c source code for the meaning of the max_lazy, good_length, nice_length, and max_chain parameters. deflateTune() can be called after deflateInit() or deflateInit2(), and returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream. */ ZEXTERN uLong ZEXPORT deflateBound(z_streamp strm, uLong sourceLen); /* deflateBound() returns an upper bound on the compressed size after deflation of sourceLen bytes. It must be called after deflateInit() or deflateInit2(), and after deflateSetHeader(), if used. This would be used to allocate an output buffer for deflation in a single pass, and so would be called before deflate(). If that first deflate() call is provided the sourceLen input bytes, an output buffer allocated to the size returned by deflateBound(), and the flush value Z_FINISH, then deflate() is guaranteed to return Z_STREAM_END. Note that it is possible for the compressed size to be larger than the value returned by deflateBound() if flush options other than Z_FINISH or Z_NO_FLUSH are used. */ ZEXTERN int ZEXPORT deflatePending(z_streamp strm, unsigned *pending, int *bits); /* deflatePending() returns the number of bytes and bits of output that have been generated, but not yet provided in the available output. The bytes not provided would be due to the available output space having being consumed. The number of bits of output not provided are between 0 and 7, where they await more bits to join them in order to fill out a full byte. If pending or bits are Z_NULL, then those values are not set. deflatePending returns Z_OK if success, or Z_STREAM_ERROR if the source stream state was inconsistent. */ ZEXTERN int ZEXPORT deflatePrime(z_streamp strm, int bits, int value); /* deflatePrime() inserts bits in the deflate output stream. The intent is that this function is used to start off the deflate output with the bits leftover from a previous deflate stream when appending to it. As such, this function can only be used for raw deflate, and must be used before the first deflate() call after a deflateInit2() or deflateReset(). bits must be less than or equal to 16, and that many of the least significant bits of value will be inserted in the output. deflatePrime returns Z_OK if success, Z_BUF_ERROR if there was not enough room in the internal buffer to insert the bits, or Z_STREAM_ERROR if the source stream state was inconsistent. */ ZEXTERN int ZEXPORT deflateSetHeader(z_streamp strm, gz_headerp head); /* deflateSetHeader() provides gzip header information for when a gzip stream is requested by deflateInit2(). deflateSetHeader() may be called after deflateInit2() or deflateReset() and before the first call of deflate(). The text, time, os, extra field, name, and comment information in the provided gz_header structure are written to the gzip header (xflag is ignored -- the extra flags are set according to the compression level). The caller must assure that, if not Z_NULL, name and comment are terminated with a zero byte, and that if extra is not Z_NULL, that extra_len bytes are available there. If hcrc is true, a gzip header crc is included. Note that the current versions of the command-line version of gzip (up through version 1.3.x) do not support header crc's, and will report that it is a "multi-part gzip file" and give up. If deflateSetHeader is not used, the default gzip header has text false, the time set to zero, and os set to the current operating system, with no extra, name, or comment fields. The gzip header is returned to the default state by deflateReset(). deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source stream state was inconsistent. */ /* ZEXTERN int ZEXPORT inflateInit2(z_streamp strm, int windowBits); This is another version of inflateInit with an extra parameter. The fields next_in, avail_in, zalloc, zfree and opaque must be initialized before by the caller. The windowBits parameter is the base two logarithm of the maximum window size (the size of the history buffer). It should be in the range 8..15 for this version of the library. The default value is 15 if inflateInit is used instead. windowBits must be greater than or equal to the windowBits value provided to deflateInit2() while compressing, or it must be equal to 15 if deflateInit2() was not used. If a compressed stream with a larger window size is given as input, inflate() will return with the error code Z_DATA_ERROR instead of trying to allocate a larger window. windowBits can also be zero to request that inflate use the window size in the zlib header of the compressed stream. windowBits can also be -8..-15 for raw inflate. In this case, -windowBits determines the window size. inflate() will then process raw deflate data, not looking for a zlib or gzip header, not generating a check value, and not looking for any check values for comparison at the end of the stream. This is for use with other formats that use the deflate compressed data format such as zip. Those formats provide their own check values. If a custom format is developed using the raw deflate format for compressed data, it is recommended that a check value such as an Adler-32 or a CRC-32 be applied to the uncompressed data as is done in the zlib, gzip, and zip formats. For most applications, the zlib format should be used as is. Note that comments above on the use in deflateInit2() applies to the magnitude of windowBits. windowBits can also be greater than 15 for optional gzip decoding. Add 32 to windowBits to enable zlib and gzip decoding with automatic header detection, or add 16 to decode only the gzip format (the zlib format will return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is a CRC-32 instead of an Adler-32. Unlike the gunzip utility and gzread() (see below), inflate() will *not* automatically decode concatenated gzip members. inflate() will return Z_STREAM_END at the end of the gzip member. The state would need to be reset to continue decoding a subsequent gzip member. This *must* be done if there is more data after a gzip member, in order for the decompression to be compliant with the gzip standard (RFC 1952). inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_VERSION_ERROR if the zlib library version is incompatible with the version assumed by the caller, or Z_STREAM_ERROR if the parameters are invalid, such as a null pointer to the structure. msg is set to null if there is no error message. inflateInit2 does not perform any decompression apart from possibly reading the zlib header if present: actual decompression will be done by inflate(). (So next_in and avail_in may be modified, but next_out and avail_out are unused and unchanged.) The current implementation of inflateInit2() does not process any header information -- that is deferred until inflate() is called. */ ZEXTERN int ZEXPORT inflateSetDictionary(z_streamp strm, const Bytef *dictionary, uInt dictLength); /* Initializes the decompression dictionary from the given uncompressed byte sequence. This function must be called immediately after a call of inflate, if that call returned Z_NEED_DICT. The dictionary chosen by the compressor can be determined from the Adler-32 value returned by that call of inflate. The compressor and decompressor must use exactly the same dictionary (see deflateSetDictionary). For raw inflate, this function can be called at any time to set the dictionary. If the provided dictionary is smaller than the window and there is already data in the window, then the provided dictionary will amend what's there. The application must insure that the dictionary that was used for compression is provided. inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the expected one (incorrect Adler-32 value). inflateSetDictionary does not perform any decompression: this will be done by subsequent calls of inflate(). */ ZEXTERN int ZEXPORT inflateGetDictionary(z_streamp strm, Bytef *dictionary, uInt *dictLength); /* Returns the sliding dictionary being maintained by inflate. dictLength is set to the number of bytes in the dictionary, and that many bytes are copied to dictionary. dictionary must have enough space, where 32768 bytes is always enough. If inflateGetDictionary() is called with dictionary equal to Z_NULL, then only the dictionary length is returned, and nothing is copied. Similarly, if dictLength is Z_NULL, then it is not set. inflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the stream state is inconsistent. */ ZEXTERN int ZEXPORT inflateSync(z_streamp strm); /* Skips invalid compressed data until a possible full flush point (see above for the description of deflate with Z_FULL_FLUSH) can be found, or until all available input is skipped. No output is provided. inflateSync searches for a 00 00 FF FF pattern in the compressed data. All full flush points have this pattern, but not all occurrences of this pattern are full flush points. inflateSync returns Z_OK if a possible full flush point has been found, Z_BUF_ERROR if no more input was provided, Z_DATA_ERROR if no flush point has been found, or Z_STREAM_ERROR if the stream structure was inconsistent. In the success case, the application may save the current value of total_in which indicates where valid compressed data was found. In the error case, the application may repeatedly call inflateSync, providing more input each time, until success or end of the input data. */ ZEXTERN int ZEXPORT inflateCopy(z_streamp dest, z_streamp source); /* Sets the destination stream as a complete copy of the source stream. This function can be useful when randomly accessing a large stream. The first pass through the stream can periodically record the inflate state, allowing restarting inflate at those points when randomly accessing the stream. inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_STREAM_ERROR if the source stream state was inconsistent (such as zalloc being Z_NULL). msg is left unchanged in both source and destination. */ ZEXTERN int ZEXPORT inflateReset(z_streamp strm); /* This function is equivalent to inflateEnd followed by inflateInit, but does not free and reallocate the internal decompression state. The stream will keep attributes that may have been set by inflateInit2. total_in, total_out, adler, and msg are initialized. inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source stream state was inconsistent (such as zalloc or state being Z_NULL). */ ZEXTERN int ZEXPORT inflateReset2(z_streamp strm, int windowBits); /* This function is the same as inflateReset, but it also permits changing the wrap and window size requests. The windowBits parameter is interpreted the same as it is for inflateInit2. If the window size is changed, then the memory allocated for the window is freed, and the window will be reallocated by inflate() if needed. inflateReset2 returns Z_OK if success, or Z_STREAM_ERROR if the source stream state was inconsistent (such as zalloc or state being Z_NULL), or if the windowBits parameter is invalid. */ ZEXTERN int ZEXPORT inflatePrime(z_streamp strm, int bits, int value); /* This function inserts bits in the inflate input stream. The intent is that this function is used to start inflating at a bit position in the middle of a byte. The provided bits will be used before any bytes are used from next_in. This function should only be used with raw inflate, and should be used before the first inflate() call after inflateInit2() or inflateReset(). bits must be less than or equal to 16, and that many of the least significant bits of value will be inserted in the input. If bits is negative, then the input stream bit buffer is emptied. Then inflatePrime() can be called again to put bits in the buffer. This is used to clear out bits leftover after feeding inflate a block description prior to feeding inflate codes. inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source stream state was inconsistent. */ ZEXTERN long ZEXPORT inflateMark(z_streamp strm); /* This function returns two values, one in the lower 16 bits of the return value, and the other in the remaining upper bits, obtained by shifting the return value down 16 bits. If the upper value is -1 and the lower value is zero, then inflate() is currently decoding information outside of a block. If the upper value is -1 and the lower value is non-zero, then inflate is in the middle of a stored block, with the lower value equaling the number of bytes from the input remaining to copy. If the upper value is not -1, then it is the number of bits back from the current bit position in the input of the code (literal or length/distance pair) currently being processed. In that case the lower value is the number of bytes already emitted for that code. A code is being processed if inflate is waiting for more input to complete decoding of the code, or if it has completed decoding but is waiting for more output space to write the literal or match data. inflateMark() is used to mark locations in the input data for random access, which may be at bit positions, and to note those cases where the output of a code may span boundaries of random access blocks. The current location in the input stream can be determined from avail_in and data_type as noted in the description for the Z_BLOCK flush parameter for inflate. inflateMark returns the value noted above, or -65536 if the provided source stream state was inconsistent. */ ZEXTERN int ZEXPORT inflateGetHeader(z_streamp strm, gz_headerp head); /* inflateGetHeader() requests that gzip header information be stored in the provided gz_header structure. inflateGetHeader() may be called after inflateInit2() or inflateReset(), and before the first call of inflate(). As inflate() processes the gzip stream, head->done is zero until the header is completed, at which time head->done is set to one. If a zlib stream is being decoded, then head->done is set to -1 to indicate that there will be no gzip header information forthcoming. Note that Z_BLOCK or Z_TREES can be used to force inflate() to return immediately after header processing is complete and before any actual data is decompressed. The text, time, xflags, and os fields are filled in with the gzip header contents. hcrc is set to true if there is a header CRC. (The header CRC was valid if done is set to one.) If extra is not Z_NULL, then extra_max contains the maximum number of bytes to write to extra. Once done is true, extra_len contains the actual extra field length, and extra contains the extra field, or that field truncated if extra_max is less than extra_len. If name is not Z_NULL, then up to name_max characters are written there, terminated with a zero unless the length is greater than name_max. If comment is not Z_NULL, then up to comm_max characters are written there, terminated with a zero unless the length is greater than comm_max. When any of extra, name, or comment are not Z_NULL and the respective field is not present in the header, then that field is set to Z_NULL to signal its absence. This allows the use of deflateSetHeader() with the returned structure to duplicate the header. However if those fields are set to allocated memory, then the application will need to save those pointers elsewhere so that they can be eventually freed. If inflateGetHeader is not used, then the header information is simply discarded. The header is always checked for validity, including the header CRC if present. inflateReset() will reset the process to discard the header information. The application would need to call inflateGetHeader() again to retrieve the header from the next gzip stream. inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source stream state was inconsistent. */ /* ZEXTERN int ZEXPORT inflateBackInit(z_streamp strm, int windowBits, unsigned char FAR *window); Initialize the internal stream state for decompression using inflateBack() calls. The fields zalloc, zfree and opaque in strm must be initialized before the call. If zalloc and zfree are Z_NULL, then the default library- derived memory allocation routines are used. windowBits is the base two logarithm of the window size, in the range 8..15. window is a caller supplied buffer of that size. Except for special applications where it is assured that deflate was used with small window sizes, windowBits must be 15 and a 32K byte window must be supplied to be able to decompress general deflate streams. See inflateBack() for the usage of these routines. inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of the parameters are invalid, Z_MEM_ERROR if the internal state could not be allocated, or Z_VERSION_ERROR if the version of the library does not match the version of the header file. */ typedef unsigned (*in_func)(void FAR *, z_const unsigned char FAR * FAR *); typedef int (*out_func)(void FAR *, unsigned char FAR *, unsigned); ZEXTERN int ZEXPORT inflateBack(z_streamp strm, in_func in, void FAR *in_desc, out_func out, void FAR *out_desc); /* inflateBack() does a raw inflate with a single call using a call-back interface for input and output. This is potentially more efficient than inflate() for file i/o applications, in that it avoids copying between the output and the sliding window by simply making the window itself the output buffer. inflate() can be faster on modern CPUs when used with large buffers. inflateBack() trusts the application to not change the output buffer passed by the output function, at least until inflateBack() returns. inflateBackInit() must be called first to allocate the internal state and to initialize the state with the user-provided window buffer. inflateBack() may then be used multiple times to inflate a complete, raw deflate stream with each call. inflateBackEnd() is then called to free the allocated state. A raw deflate stream is one with no zlib or gzip header or trailer. This routine would normally be used in a utility that reads zip or gzip files and writes out uncompressed files. The utility would decode the header and process the trailer on its own, hence this routine expects only the raw deflate stream to decompress. This is different from the default behavior of inflate(), which expects a zlib header and trailer around the deflate stream. inflateBack() uses two subroutines supplied by the caller that are then called by inflateBack() for input and output. inflateBack() calls those routines until it reads a complete deflate stream and writes out all of the uncompressed data, or until it encounters an error. The function's parameters and return types are defined above in the in_func and out_func typedefs. inflateBack() will call in(in_desc, &buf) which should return the number of bytes of provided input, and a pointer to that input in buf. If there is no input available, in() must return zero -- buf is ignored in that case -- and inflateBack() will return a buffer error. inflateBack() will call out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. out() should return zero on success, or non-zero on failure. If out() returns non-zero, inflateBack() will return with an error. Neither in() nor out() are permitted to change the contents of the window provided to inflateBackInit(), which is also the buffer that out() uses to write from. The length written by out() will be at most the window size. Any non-zero amount of input may be provided by in(). For convenience, inflateBack() can be provided input on the first call by setting strm->next_in and strm->avail_in. If that input is exhausted, then in() will be called. Therefore strm->next_in must be initialized before calling inflateBack(). If strm->next_in is Z_NULL, then in() will be called immediately for input. If strm->next_in is not Z_NULL, then strm->avail_in must also be initialized, and then if strm->avail_in is not zero, input will initially be taken from strm->next_in[0 .. strm->avail_in - 1]. The in_desc and out_desc parameters of inflateBack() is passed as the first parameter of in() and out() respectively when they are called. These descriptors can be optionally used to pass any information that the caller- supplied in() and out() functions need to do their job. On return, inflateBack() will set strm->next_in and strm->avail_in to pass back any unused input that was provided by the last in() call. The return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR if in() or out() returned an error, Z_DATA_ERROR if there was a format error in the deflate stream (in which case strm->msg is set to indicate the nature of the error), or Z_STREAM_ERROR if the stream was not properly initialized. In the case of Z_BUF_ERROR, an input or output error can be distinguished using strm->next_in which will be Z_NULL only if in() returned an error. If strm->next_in is not Z_NULL, then the Z_BUF_ERROR was due to out() returning non-zero. (in() will always be called before out(), so strm->next_in is assured to be defined if out() returns non-zero.) Note that inflateBack() cannot return Z_OK. */ ZEXTERN int ZEXPORT inflateBackEnd(z_streamp strm); /* All memory allocated by inflateBackInit() is freed. inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream state was inconsistent. */ ZEXTERN uLong ZEXPORT zlibCompileFlags(void); /* Return flags indicating compile-time options. Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other: 1.0: size of uInt 3.2: size of uLong 5.4: size of voidpf (pointer) 7.6: size of z_off_t Compiler, assembler, and debug options: 8: ZLIB_DEBUG 9: ASMV or ASMINF -- use ASM code 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention 11: 0 (reserved) One-time table building (smaller code, but not thread-safe if true): 12: BUILDFIXED -- build static block decoding tables when needed 13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed 14,15: 0 (reserved) Library content (indicates missing functionality): 16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking deflate code when not needed) 17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect and decode gzip streams (to avoid linking crc code) 18-19: 0 (reserved) Operation variations (changes in library functionality): 20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate 21: FASTEST -- deflate algorithm with only one, lowest compression level 22,23: 0 (reserved) The sprintf variant used by gzprintf (zero is best): 24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format 25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure! 26: 0 = returns value, 1 = void -- 1 means inferred string length returned Remainder: 27-31: 0 (reserved) */ #ifndef Z_SOLO /* utility functions */ /* The following utility functions are implemented on top of the basic stream-oriented functions. To simplify the interface, some default options are assumed (compression level and memory usage, standard memory allocation functions). The source code of these utility functions can be modified if you need special options. */ ZEXTERN int ZEXPORT compress(Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen); /* Compresses the source buffer into the destination buffer. sourceLen is the byte length of the source buffer. Upon entry, destLen is the total size of the destination buffer, which must be at least the value returned by compressBound(sourceLen). Upon exit, destLen is the actual size of the compressed data. compress() is equivalent to compress2() with a level parameter of Z_DEFAULT_COMPRESSION. compress returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR if there was not enough room in the output buffer. */ ZEXTERN int ZEXPORT compress2(Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen, int level); /* Compresses the source buffer into the destination buffer. The level parameter has the same meaning as in deflateInit. sourceLen is the byte length of the source buffer. Upon entry, destLen is the total size of the destination buffer, which must be at least the value returned by compressBound(sourceLen). Upon exit, destLen is the actual size of the compressed data. compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR if there was not enough room in the output buffer, Z_STREAM_ERROR if the level parameter is invalid. */ ZEXTERN uLong ZEXPORT compressBound(uLong sourceLen); /* compressBound() returns an upper bound on the compressed size after compress() or compress2() on sourceLen bytes. It would be used before a compress() or compress2() call to allocate the destination buffer. */ ZEXTERN int ZEXPORT uncompress(Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen); /* Decompresses the source buffer into the destination buffer. sourceLen is the byte length of the source buffer. Upon entry, destLen is the total size of the destination buffer, which must be large enough to hold the entire uncompressed data. (The size of the uncompressed data must have been saved previously by the compressor and transmitted to the decompressor by some mechanism outside the scope of this compression library.) Upon exit, destLen is the actual size of the uncompressed data. uncompress returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR if there was not enough room in the output buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. In the case where there is not enough room, uncompress() will fill the output buffer with the uncompressed data up to that point. */ ZEXTERN int ZEXPORT uncompress2(Bytef *dest, uLongf *destLen, const Bytef *source, uLong *sourceLen); /* Same as uncompress, except that sourceLen is a pointer, where the length of the source is *sourceLen. On return, *sourceLen is the number of source bytes consumed. */ /* gzip file access functions */ /* This library supports reading and writing files in gzip (.gz) format with an interface similar to that of stdio, using the functions that start with "gz". The gzip format is different from the zlib format. gzip is a gzip wrapper, documented in RFC 1952, wrapped around a deflate stream. */ typedef struct gzFile_s *gzFile; /* semi-opaque gzip file descriptor */ /* ZEXTERN gzFile ZEXPORT gzopen(const char *path, const char *mode); Open the gzip (.gz) file at path for reading and decompressing, or compressing and writing. The mode parameter is as in fopen ("rb" or "wb") but can also include a compression level ("wb9") or a strategy: 'f' for filtered data as in "wb6f", 'h' for Huffman-only compression as in "wb1h", 'R' for run-length encoding as in "wb1R", or 'F' for fixed code compression as in "wb9F". (See the description of deflateInit2 for more information about the strategy parameter.) 'T' will request transparent writing or appending with no compression and not using the gzip format. "a" can be used instead of "w" to request that the gzip stream that will be written be appended to the file. "+" will result in an error, since reading and writing to the same gzip file is not supported. The addition of "x" when writing will create the file exclusively, which fails if the file already exists. On systems that support it, the addition of "e" when reading or writing will set the flag to close the file on an execve() call. These functions, as well as gzip, will read and decode a sequence of gzip streams in a file. The append function of gzopen() can be used to create such a file. (Also see gzflush() for another way to do this.) When appending, gzopen does not test whether the file begins with a gzip stream, nor does it look for the end of the gzip streams to begin appending. gzopen will simply append a gzip stream to the existing file. gzopen can be used to read a file which is not in gzip format; in this case gzread will directly read from the file without decompression. When reading, this will be detected automatically by looking for the magic two- byte gzip header. gzopen returns NULL if the file could not be opened, if there was insufficient memory to allocate the gzFile state, or if an invalid mode was specified (an 'r', 'w', or 'a' was not provided, or '+' was provided). errno can be checked to determine if the reason gzopen failed was that the file could not be opened. */ ZEXTERN gzFile ZEXPORT gzdopen(int fd, const char *mode); /* Associate a gzFile with the file descriptor fd. File descriptors are obtained from calls like open, dup, creat, pipe or fileno (if the file has been previously opened with fopen). The mode parameter is as in gzopen. The next call of gzclose on the returned gzFile will also close the file descriptor fd, just like fclose(fdopen(fd, mode)) closes the file descriptor fd. If you want to keep fd open, use fd = dup(fd_keep); gz = gzdopen(fd, mode);. The duplicated descriptor should be saved to avoid a leak, since gzdopen does not close fd if it fails. If you are using fileno() to get the file descriptor from a FILE *, then you will have to use dup() to avoid double-close()ing the file descriptor. Both gzclose() and fclose() will close the associated file descriptor, so they need to have different file descriptors. gzdopen returns NULL if there was insufficient memory to allocate the gzFile state, if an invalid mode was specified (an 'r', 'w', or 'a' was not provided, or '+' was provided), or if fd is -1. The file descriptor is not used until the next gz* read, write, seek, or close operation, so gzdopen will not detect if fd is invalid (unless fd is -1). */ ZEXTERN int ZEXPORT gzbuffer(gzFile file, unsigned size); /* Set the internal buffer size used by this library's functions for file to size. The default buffer size is 8192 bytes. This function must be called after gzopen() or gzdopen(), and before any other calls that read or write the file. The buffer memory allocation is always deferred to the first read or write. Three times that size in buffer space is allocated. A larger buffer size of, for example, 64K or 128K bytes will noticeably increase the speed of decompression (reading). The new buffer size also affects the maximum length for gzprintf(). gzbuffer() returns 0 on success, or -1 on failure, such as being called too late. */ ZEXTERN int ZEXPORT gzsetparams(gzFile file, int level, int strategy); /* Dynamically update the compression level and strategy for file. See the description of deflateInit2 for the meaning of these parameters. Previously provided data is flushed before applying the parameter changes. gzsetparams returns Z_OK if success, Z_STREAM_ERROR if the file was not opened for writing, Z_ERRNO if there is an error writing the flushed data, or Z_MEM_ERROR if there is a memory allocation error. */ ZEXTERN int ZEXPORT gzread(gzFile file, voidp buf, unsigned len); /* Read and decompress up to len uncompressed bytes from file into buf. If the input file is not in gzip format, gzread copies the given number of bytes into the buffer directly from the file. After reaching the end of a gzip stream in the input, gzread will continue to read, looking for another gzip stream. Any number of gzip streams may be concatenated in the input file, and will all be decompressed by gzread(). If something other than a gzip stream is encountered after a gzip stream, that remaining trailing garbage is ignored (and no error is returned). gzread can be used to read a gzip file that is being concurrently written. Upon reaching the end of the input, gzread will return with the available data. If the error code returned by gzerror is Z_OK or Z_BUF_ERROR, then gzclearerr can be used to clear the end of file indicator in order to permit gzread to be tried again. Z_OK indicates that a gzip stream was completed on the last gzread. Z_BUF_ERROR indicates that the input file ended in the middle of a gzip stream. Note that gzread does not return -1 in the event of an incomplete gzip stream. This error is deferred until gzclose(), which will return Z_BUF_ERROR if the last gzread ended in the middle of a gzip stream. Alternatively, gzerror can be used before gzclose to detect this case. gzread returns the number of uncompressed bytes actually read, less than len for end of file, or -1 for error. If len is too large to fit in an int, then nothing is read, -1 is returned, and the error state is set to Z_STREAM_ERROR. */ ZEXTERN z_size_t ZEXPORT gzfread(voidp buf, z_size_t size, z_size_t nitems, gzFile file); /* Read and decompress up to nitems items of size size from file into buf, otherwise operating as gzread() does. This duplicates the interface of stdio's fread(), with size_t request and return types. If the library defines size_t, then z_size_t is identical to size_t. If not, then z_size_t is an unsigned integer type that can contain a pointer. gzfread() returns the number of full items read of size size, or zero if the end of the file was reached and a full item could not be read, or if there was an error. gzerror() must be consulted if zero is returned in order to determine if there was an error. If the multiplication of size and nitems overflows, i.e. the product does not fit in a z_size_t, then nothing is read, zero is returned, and the error state is set to Z_STREAM_ERROR. In the event that the end of file is reached and only a partial item is available at the end, i.e. the remaining uncompressed data length is not a multiple of size, then the final partial item is nevertheless read into buf and the end-of-file flag is set. The length of the partial item read is not provided, but could be inferred from the result of gztell(). This behavior is the same as the behavior of fread() implementations in common libraries, but it prevents the direct use of gzfread() to read a concurrently written file, resetting and retrying on end-of-file, when size is not 1. */ ZEXTERN int ZEXPORT gzwrite(gzFile file, voidpc buf, unsigned len); /* Compress and write the len uncompressed bytes at buf to file. gzwrite returns the number of uncompressed bytes written or 0 in case of error. */ ZEXTERN z_size_t ZEXPORT gzfwrite(voidpc buf, z_size_t size, z_size_t nitems, gzFile file); /* Compress and write nitems items of size size from buf to file, duplicating the interface of stdio's fwrite(), with size_t request and return types. If the library defines size_t, then z_size_t is identical to size_t. If not, then z_size_t is an unsigned integer type that can contain a pointer. gzfwrite() returns the number of full items written of size size, or zero if there was an error. If the multiplication of size and nitems overflows, i.e. the product does not fit in a z_size_t, then nothing is written, zero is returned, and the error state is set to Z_STREAM_ERROR. */ ZEXTERN int ZEXPORTVA gzprintf(gzFile file, const char *format, ...); /* Convert, format, compress, and write the arguments (...) to file under control of the string format, as in fprintf. gzprintf returns the number of uncompressed bytes actually written, or a negative zlib error code in case of error. The number of uncompressed bytes written is limited to 8191, or one less than the buffer size given to gzbuffer(). The caller should assure that this limit is not exceeded. If it is exceeded, then gzprintf() will return an error (0) with nothing written. In this case, there may also be a buffer overflow with unpredictable consequences, which is possible only if zlib was compiled with the insecure functions sprintf() or vsprintf(), because the secure snprintf() or vsnprintf() functions were not available. This can be determined using zlibCompileFlags(). */ ZEXTERN int ZEXPORT gzputs(gzFile file, const char *s); /* Compress and write the given null-terminated string s to file, excluding the terminating null character. gzputs returns the number of characters written, or -1 in case of error. */ ZEXTERN char * ZEXPORT gzgets(gzFile file, char *buf, int len); /* Read and decompress bytes from file into buf, until len-1 characters are read, or until a newline character is read and transferred to buf, or an end-of-file condition is encountered. If any characters are read or if len is one, the string is terminated with a null character. If no characters are read due to an end-of-file or len is less than one, then the buffer is left untouched. gzgets returns buf which is a null-terminated string, or it returns NULL for end-of-file or in case of error. If there was an error, the contents at buf are indeterminate. */ ZEXTERN int ZEXPORT gzputc(gzFile file, int c); /* Compress and write c, converted to an unsigned char, into file. gzputc returns the value that was written, or -1 in case of error. */ ZEXTERN int ZEXPORT gzgetc(gzFile file); /* Read and decompress one byte from file. gzgetc returns this byte or -1 in case of end of file or error. This is implemented as a macro for speed. As such, it does not do all of the checking the other functions do. I.e. it does not check to see if file is NULL, nor whether the structure file points to has been clobbered or not. */ ZEXTERN int ZEXPORT gzungetc(int c, gzFile file); /* Push c back onto the stream for file to be read as the first character on the next read. At least one character of push-back is always allowed. gzungetc() returns the character pushed, or -1 on failure. gzungetc() will fail if c is -1, and may fail if a character has been pushed but not read yet. If gzungetc is used immediately after gzopen or gzdopen, at least the output buffer size of pushed characters is allowed. (See gzbuffer above.) The pushed character will be discarded if the stream is repositioned with gzseek() or gzrewind(). */ ZEXTERN int ZEXPORT gzflush(gzFile file, int flush); /* Flush all pending output to file. The parameter flush is as in the deflate() function. The return value is the zlib error number (see function gzerror below). gzflush is only permitted when writing. If the flush parameter is Z_FINISH, the remaining data is written and the gzip stream is completed in the output. If gzwrite() is called again, a new gzip stream will be started in the output. gzread() is able to read such concatenated gzip streams. gzflush should be called only when strictly necessary because it will degrade compression if called too often. */ /* ZEXTERN z_off_t ZEXPORT gzseek(gzFile file, z_off_t offset, int whence); Set the starting position to offset relative to whence for the next gzread or gzwrite on file. The offset represents a number of bytes in the uncompressed data stream. The whence parameter is defined as in lseek(2); the value SEEK_END is not supported. If the file is opened for reading, this function is emulated but can be extremely slow. If the file is opened for writing, only forward seeks are supported; gzseek then compresses a sequence of zeroes up to the new starting position. gzseek returns the resulting offset location as measured in bytes from the beginning of the uncompressed stream, or -1 in case of error, in particular if the file is opened for writing and the new starting position would be before the current position. */ ZEXTERN int ZEXPORT gzrewind(gzFile file); /* Rewind file. This function is supported only for reading. gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET). */ /* ZEXTERN z_off_t ZEXPORT gztell(gzFile file); Return the starting position for the next gzread or gzwrite on file. This position represents a number of bytes in the uncompressed data stream, and is zero when starting, even if appending or reading a gzip stream from the middle of a file using gzdopen(). gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) */ /* ZEXTERN z_off_t ZEXPORT gzoffset(gzFile file); Return the current compressed (actual) read or write offset of file. This offset includes the count of bytes that precede the gzip stream, for example when appending or when using gzdopen() for reading. When reading, the offset does not include as yet unused buffered input. This information can be used for a progress indicator. On error, gzoffset() returns -1. */ ZEXTERN int ZEXPORT gzeof(gzFile file); /* Return true (1) if the end-of-file indicator for file has been set while reading, false (0) otherwise. Note that the end-of-file indicator is set only if the read tried to go past the end of the input, but came up short. Therefore, just like feof(), gzeof() may return false even if there is no more data to read, in the event that the last read request was for the exact number of bytes remaining in the input file. This will happen if the input file size is an exact multiple of the buffer size. If gzeof() returns true, then the read functions will return no more data, unless the end-of-file indicator is reset by gzclearerr() and the input file has grown since the previous end of file was detected. */ ZEXTERN int ZEXPORT gzdirect(gzFile file); /* Return true (1) if file is being copied directly while reading, or false (0) if file is a gzip stream being decompressed. If the input file is empty, gzdirect() will return true, since the input does not contain a gzip stream. If gzdirect() is used immediately after gzopen() or gzdopen() it will cause buffers to be allocated to allow reading the file to determine if it is a gzip file. Therefore if gzbuffer() is used, it should be called before gzdirect(). When writing, gzdirect() returns true (1) if transparent writing was requested ("wT" for the gzopen() mode), or false (0) otherwise. (Note: gzdirect() is not needed when writing. Transparent writing must be explicitly requested, so the application already knows the answer. When linking statically, using gzdirect() will include all of the zlib code for gzip file reading and decompression, which may not be desired.) */ ZEXTERN int ZEXPORT gzclose(gzFile file); /* Flush all pending output for file, if necessary, close file and deallocate the (de)compression state. Note that once file is closed, you cannot call gzerror with file, since its structures have been deallocated. gzclose must not be called more than once on the same file, just as free must not be called more than once on the same allocation. gzclose will return Z_STREAM_ERROR if file is not valid, Z_ERRNO on a file operation error, Z_MEM_ERROR if out of memory, Z_BUF_ERROR if the last read ended in the middle of a gzip stream, or Z_OK on success. */ ZEXTERN int ZEXPORT gzclose_r(gzFile file); ZEXTERN int ZEXPORT gzclose_w(gzFile file); /* Same as gzclose(), but gzclose_r() is only for use when reading, and gzclose_w() is only for use when writing or appending. The advantage to using these instead of gzclose() is that they avoid linking in zlib compression or decompression code that is not used when only reading or only writing respectively. If gzclose() is used, then both compression and decompression code will be included the application when linking to a static zlib library. */ ZEXTERN const char * ZEXPORT gzerror(gzFile file, int *errnum); /* Return the error message for the last error which occurred on file. errnum is set to zlib error number. If an error occurred in the file system and not in the compression library, errnum is set to Z_ERRNO and the application may consult errno to get the exact error code. The application must not modify the returned string. Future calls to this function may invalidate the previously returned string. If file is closed, then the string previously returned by gzerror will no longer be available. gzerror() should be used to distinguish errors from end-of-file for those functions above that do not distinguish those cases in their return values. */ ZEXTERN void ZEXPORT gzclearerr(gzFile file); /* Clear the error and end-of-file flags for file. This is analogous to the clearerr() function in stdio. This is useful for continuing to read a gzip file that is being written concurrently. */ #endif /* !Z_SOLO */ /* checksum functions */ /* These functions are not related to compression but are exported anyway because they might be useful in applications using the compression library. */ ZEXTERN uLong ZEXPORT adler32(uLong adler, const Bytef *buf, uInt len); /* Update a running Adler-32 checksum with the bytes buf[0..len-1] and return the updated checksum. An Adler-32 value is in the range of a 32-bit unsigned integer. If buf is Z_NULL, this function returns the required initial value for the checksum. An Adler-32 checksum is almost as reliable as a CRC-32 but can be computed much faster. Usage example: uLong adler = adler32(0L, Z_NULL, 0); while (read_buffer(buffer, length) != EOF) { adler = adler32(adler, buffer, length); } if (adler != original_adler) error(); */ ZEXTERN uLong ZEXPORT adler32_z(uLong adler, const Bytef *buf, z_size_t len); /* Same as adler32(), but with a size_t length. */ /* ZEXTERN uLong ZEXPORT adler32_combine(uLong adler1, uLong adler2, z_off_t len2); Combine two Adler-32 checksums into one. For two sequences of bytes, seq1 and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for each, adler1 and adler2. adler32_combine() returns the Adler-32 checksum of seq1 and seq2 concatenated, requiring only adler1, adler2, and len2. Note that the z_off_t type (like off_t) is a signed integer. If len2 is negative, the result has no meaning or utility. */ ZEXTERN uLong ZEXPORT crc32(uLong crc, const Bytef *buf, uInt len); /* Update a running CRC-32 with the bytes buf[0..len-1] and return the updated CRC-32. A CRC-32 value is in the range of a 32-bit unsigned integer. If buf is Z_NULL, this function returns the required initial value for the crc. Pre- and post-conditioning (one's complement) is performed within this function so it shouldn't be done by the application. Usage example: uLong crc = crc32(0L, Z_NULL, 0); while (read_buffer(buffer, length) != EOF) { crc = crc32(crc, buffer, length); } if (crc != original_crc) error(); */ ZEXTERN uLong ZEXPORT crc32_z(uLong crc, const Bytef *buf, z_size_t len); /* Same as crc32(), but with a size_t length. */ /* ZEXTERN uLong ZEXPORT crc32_combine(uLong crc1, uLong crc2, z_off_t len2); Combine two CRC-32 check values into one. For two sequences of bytes, seq1 and seq2 with lengths len1 and len2, CRC-32 check values were calculated for each, crc1 and crc2. crc32_combine() returns the CRC-32 check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and len2. len2 must be non-negative. */ /* ZEXTERN uLong ZEXPORT crc32_combine_gen(z_off_t len2); Return the operator corresponding to length len2, to be used with crc32_combine_op(). len2 must be non-negative. */ ZEXTERN uLong ZEXPORT crc32_combine_op(uLong crc1, uLong crc2, uLong op); /* Give the same result as crc32_combine(), using op in place of len2. op is is generated from len2 by crc32_combine_gen(). This will be faster than crc32_combine() if the generated op is used more than once. */ /* various hacks, don't look :) */ /* deflateInit and inflateInit are macros to allow checking the zlib version * and the compiler's view of z_stream: */ ZEXTERN int ZEXPORT deflateInit_(z_streamp strm, int level, const char *version, int stream_size); ZEXTERN int ZEXPORT inflateInit_(z_streamp strm, const char *version, int stream_size); ZEXTERN int ZEXPORT deflateInit2_(z_streamp strm, int level, int method, int windowBits, int memLevel, int strategy, const char *version, int stream_size); ZEXTERN int ZEXPORT inflateInit2_(z_streamp strm, int windowBits, const char *version, int stream_size); ZEXTERN int ZEXPORT inflateBackInit_(z_streamp strm, int windowBits, unsigned char FAR *window, const char *version, int stream_size); #ifdef Z_PREFIX_SET # define z_deflateInit(strm, level) \ deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream)) # define z_inflateInit(strm) \ inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream)) # define z_deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ (strategy), ZLIB_VERSION, (int)sizeof(z_stream)) # define z_inflateInit2(strm, windowBits) \ inflateInit2_((strm), (windowBits), ZLIB_VERSION, \ (int)sizeof(z_stream)) # define z_inflateBackInit(strm, windowBits, window) \ inflateBackInit_((strm), (windowBits), (window), \ ZLIB_VERSION, (int)sizeof(z_stream)) #else # define deflateInit(strm, level) \ deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream)) # define inflateInit(strm) \ inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream)) # define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ (strategy), ZLIB_VERSION, (int)sizeof(z_stream)) # define inflateInit2(strm, windowBits) \ inflateInit2_((strm), (windowBits), ZLIB_VERSION, \ (int)sizeof(z_stream)) # define inflateBackInit(strm, windowBits, window) \ inflateBackInit_((strm), (windowBits), (window), \ ZLIB_VERSION, (int)sizeof(z_stream)) #endif #ifndef Z_SOLO /* gzgetc() macro and its supporting function and exposed data structure. Note * that the real internal state is much larger than the exposed structure. * This abbreviated structure exposes just enough for the gzgetc() macro. The * user should not mess with these exposed elements, since their names or * behavior could change in the future, perhaps even capriciously. They can * only be used by the gzgetc() macro. You have been warned. */ struct gzFile_s { unsigned have; unsigned char *next; z_off64_t pos; }; ZEXTERN int ZEXPORT gzgetc_(gzFile file); /* backward compatibility */ #ifdef Z_PREFIX_SET # undef z_gzgetc # define z_gzgetc(g) \ ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : (gzgetc)(g)) #else # define gzgetc(g) \ ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : (gzgetc)(g)) #endif /* provide 64-bit offset functions if _LARGEFILE64_SOURCE defined, and/or * change the regular functions to 64 bits if _FILE_OFFSET_BITS is 64 (if * both are true, the application gets the *64 functions, and the regular * functions are changed to 64 bits) -- in case these are set on systems * without large file support, _LFS64_LARGEFILE must also be true */ #ifdef Z_LARGE64 ZEXTERN gzFile ZEXPORT gzopen64(const char *, const char *); ZEXTERN z_off64_t ZEXPORT gzseek64(gzFile, z_off64_t, int); ZEXTERN z_off64_t ZEXPORT gztell64(gzFile); ZEXTERN z_off64_t ZEXPORT gzoffset64(gzFile); ZEXTERN uLong ZEXPORT adler32_combine64(uLong, uLong, z_off64_t); ZEXTERN uLong ZEXPORT crc32_combine64(uLong, uLong, z_off64_t); ZEXTERN uLong ZEXPORT crc32_combine_gen64(z_off64_t); #endif #if !defined(ZLIB_INTERNAL) && defined(Z_WANT64) # ifdef Z_PREFIX_SET # define z_gzopen z_gzopen64 # define z_gzseek z_gzseek64 # define z_gztell z_gztell64 # define z_gzoffset z_gzoffset64 # define z_adler32_combine z_adler32_combine64 # define z_crc32_combine z_crc32_combine64 # define z_crc32_combine_gen z_crc32_combine_gen64 # else # define gzopen gzopen64 # define gzseek gzseek64 # define gztell gztell64 # define gzoffset gzoffset64 # define adler32_combine adler32_combine64 # define crc32_combine crc32_combine64 # define crc32_combine_gen crc32_combine_gen64 # endif # ifndef Z_LARGE64 ZEXTERN gzFile ZEXPORT gzopen64(const char *, const char *); ZEXTERN z_off_t ZEXPORT gzseek64(gzFile, z_off_t, int); ZEXTERN z_off_t ZEXPORT gztell64(gzFile); ZEXTERN z_off_t ZEXPORT gzoffset64(gzFile); ZEXTERN uLong ZEXPORT adler32_combine64(uLong, uLong, z_off_t); ZEXTERN uLong ZEXPORT crc32_combine64(uLong, uLong, z_off_t); ZEXTERN uLong ZEXPORT crc32_combine_gen64(z_off_t); # endif #else ZEXTERN gzFile ZEXPORT gzopen(const char *, const char *); ZEXTERN z_off_t ZEXPORT gzseek(gzFile, z_off_t, int); ZEXTERN z_off_t ZEXPORT gztell(gzFile); ZEXTERN z_off_t ZEXPORT gzoffset(gzFile); ZEXTERN uLong ZEXPORT adler32_combine(uLong, uLong, z_off_t); ZEXTERN uLong ZEXPORT crc32_combine(uLong, uLong, z_off_t); ZEXTERN uLong ZEXPORT crc32_combine_gen(z_off_t); #endif #else /* Z_SOLO */ ZEXTERN uLong ZEXPORT adler32_combine(uLong, uLong, z_off_t); ZEXTERN uLong ZEXPORT crc32_combine(uLong, uLong, z_off_t); ZEXTERN uLong ZEXPORT crc32_combine_gen(z_off_t); #endif /* !Z_SOLO */ /* undocumented functions */ ZEXTERN const char * ZEXPORT zError(int); ZEXTERN int ZEXPORT inflateSyncPoint(z_streamp); ZEXTERN const z_crc_t FAR * ZEXPORT get_crc_table(void); ZEXTERN int ZEXPORT inflateUndermine(z_streamp, int); ZEXTERN int ZEXPORT inflateValidate(z_streamp, int); ZEXTERN unsigned long ZEXPORT inflateCodesUsed(z_streamp); ZEXTERN int ZEXPORT inflateResetKeep(z_streamp); ZEXTERN int ZEXPORT deflateResetKeep(z_streamp); #if defined(_WIN32) && !defined(Z_SOLO) ZEXTERN gzFile ZEXPORT gzopen_w(const wchar_t *path, const char *mode); #endif #if defined(STDC) || defined(Z_HAVE_STDARG_H) # ifndef Z_SOLO ZEXTERN int ZEXPORTVA gzvprintf(gzFile file, const char *format, va_list va); # endif #endif #ifdef __cplusplus } #endif #endif /* ZLIB_H */ opengnb-ver1.6.0.a/libs/zlib/zutil.c000066400000000000000000000160131500454252100173050ustar00rootroot00000000000000/* zutil.c -- target dependent utility functions for the compression library * Copyright (C) 1995-2017 Jean-loup Gailly * For conditions of distribution and use, see copyright notice in zlib.h */ /* @(#) $Id$ */ #include "zutil.h" #ifndef Z_SOLO # include "gzguts.h" #endif z_const char * const z_errmsg[10] = { (z_const char *)"need dictionary", /* Z_NEED_DICT 2 */ (z_const char *)"stream end", /* Z_STREAM_END 1 */ (z_const char *)"", /* Z_OK 0 */ (z_const char *)"file error", /* Z_ERRNO (-1) */ (z_const char *)"stream error", /* Z_STREAM_ERROR (-2) */ (z_const char *)"data error", /* Z_DATA_ERROR (-3) */ (z_const char *)"insufficient memory", /* Z_MEM_ERROR (-4) */ (z_const char *)"buffer error", /* Z_BUF_ERROR (-5) */ (z_const char *)"incompatible version",/* Z_VERSION_ERROR (-6) */ (z_const char *)"" }; const char * ZEXPORT zlibVersion(void) { return ZLIB_VERSION; } uLong ZEXPORT zlibCompileFlags(void) { uLong flags; flags = 0; switch ((int)(sizeof(uInt))) { case 2: break; case 4: flags += 1; break; case 8: flags += 2; break; default: flags += 3; } switch ((int)(sizeof(uLong))) { case 2: break; case 4: flags += 1 << 2; break; case 8: flags += 2 << 2; break; default: flags += 3 << 2; } switch ((int)(sizeof(voidpf))) { case 2: break; case 4: flags += 1 << 4; break; case 8: flags += 2 << 4; break; default: flags += 3 << 4; } switch ((int)(sizeof(z_off_t))) { case 2: break; case 4: flags += 1 << 6; break; case 8: flags += 2 << 6; break; default: flags += 3 << 6; } #ifdef ZLIB_DEBUG flags += 1 << 8; #endif /* #if defined(ASMV) || defined(ASMINF) flags += 1 << 9; #endif */ #ifdef ZLIB_WINAPI flags += 1 << 10; #endif #ifdef BUILDFIXED flags += 1 << 12; #endif #ifdef DYNAMIC_CRC_TABLE flags += 1 << 13; #endif #ifdef NO_GZCOMPRESS flags += 1L << 16; #endif #ifdef NO_GZIP flags += 1L << 17; #endif #ifdef PKZIP_BUG_WORKAROUND flags += 1L << 20; #endif #ifdef FASTEST flags += 1L << 21; #endif #if defined(STDC) || defined(Z_HAVE_STDARG_H) # ifdef NO_vsnprintf flags += 1L << 25; # ifdef HAS_vsprintf_void flags += 1L << 26; # endif # else # ifdef HAS_vsnprintf_void flags += 1L << 26; # endif # endif #else flags += 1L << 24; # ifdef NO_snprintf flags += 1L << 25; # ifdef HAS_sprintf_void flags += 1L << 26; # endif # else # ifdef HAS_snprintf_void flags += 1L << 26; # endif # endif #endif return flags; } #ifdef ZLIB_DEBUG #include # ifndef verbose # define verbose 0 # endif int ZLIB_INTERNAL z_verbose = verbose; void ZLIB_INTERNAL z_error(char *m) { fprintf(stderr, "%s\n", m); exit(1); } #endif /* exported to allow conversion of error code to string for compress() and * uncompress() */ const char * ZEXPORT zError(int err) { return ERR_MSG(err); } #if defined(_WIN32_WCE) && _WIN32_WCE < 0x800 /* The older Microsoft C Run-Time Library for Windows CE doesn't have * errno. We define it as a global variable to simplify porting. * Its value is always 0 and should not be used. */ int errno = 0; #endif #ifndef HAVE_MEMCPY void ZLIB_INTERNAL zmemcpy(Bytef* dest, const Bytef* source, uInt len) { if (len == 0) return; do { *dest++ = *source++; /* ??? to be unrolled */ } while (--len != 0); } int ZLIB_INTERNAL zmemcmp(const Bytef* s1, const Bytef* s2, uInt len) { uInt j; for (j = 0; j < len; j++) { if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1; } return 0; } void ZLIB_INTERNAL zmemzero(Bytef* dest, uInt len) { if (len == 0) return; do { *dest++ = 0; /* ??? to be unrolled */ } while (--len != 0); } #endif #ifndef Z_SOLO #ifdef SYS16BIT #ifdef __TURBOC__ /* Turbo C in 16-bit mode */ # define MY_ZCALLOC /* Turbo C malloc() does not allow dynamic allocation of 64K bytes * and farmalloc(64K) returns a pointer with an offset of 8, so we * must fix the pointer. Warning: the pointer must be put back to its * original form in order to free it, use zcfree(). */ #define MAX_PTR 10 /* 10*64K = 640K */ local int next_ptr = 0; typedef struct ptr_table_s { voidpf org_ptr; voidpf new_ptr; } ptr_table; local ptr_table table[MAX_PTR]; /* This table is used to remember the original form of pointers * to large buffers (64K). Such pointers are normalized with a zero offset. * Since MSDOS is not a preemptive multitasking OS, this table is not * protected from concurrent access. This hack doesn't work anyway on * a protected system like OS/2. Use Microsoft C instead. */ voidpf ZLIB_INTERNAL zcalloc(voidpf opaque, unsigned items, unsigned size) { voidpf buf; ulg bsize = (ulg)items*size; (void)opaque; /* If we allocate less than 65520 bytes, we assume that farmalloc * will return a usable pointer which doesn't have to be normalized. */ if (bsize < 65520L) { buf = farmalloc(bsize); if (*(ush*)&buf != 0) return buf; } else { buf = farmalloc(bsize + 16L); } if (buf == NULL || next_ptr >= MAX_PTR) return NULL; table[next_ptr].org_ptr = buf; /* Normalize the pointer to seg:0 */ *((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4; *(ush*)&buf = 0; table[next_ptr++].new_ptr = buf; return buf; } void ZLIB_INTERNAL zcfree(voidpf opaque, voidpf ptr) { int n; (void)opaque; if (*(ush*)&ptr != 0) { /* object < 64K */ farfree(ptr); return; } /* Find the original pointer */ for (n = 0; n < next_ptr; n++) { if (ptr != table[n].new_ptr) continue; farfree(table[n].org_ptr); while (++n < next_ptr) { table[n-1] = table[n]; } next_ptr--; return; } Assert(0, "zcfree: ptr not found"); } #endif /* __TURBOC__ */ #ifdef M_I86 /* Microsoft C in 16-bit mode */ # define MY_ZCALLOC #if (!defined(_MSC_VER) || (_MSC_VER <= 600)) # define _halloc halloc # define _hfree hfree #endif voidpf ZLIB_INTERNAL zcalloc(voidpf opaque, uInt items, uInt size) { (void)opaque; return _halloc((long)items, size); } void ZLIB_INTERNAL zcfree(voidpf opaque, voidpf ptr) { (void)opaque; _hfree(ptr); } #endif /* M_I86 */ #endif /* SYS16BIT */ #ifndef MY_ZCALLOC /* Any system without a special alloc function */ #ifndef STDC extern voidp malloc(uInt size); extern voidp calloc(uInt items, uInt size); extern void free(voidpf ptr); #endif voidpf ZLIB_INTERNAL zcalloc(voidpf opaque, unsigned items, unsigned size) { (void)opaque; return sizeof(uInt) > 2 ? (voidpf)malloc(items * size) : (voidpf)calloc(items, size); } void ZLIB_INTERNAL zcfree(voidpf opaque, voidpf ptr) { (void)opaque; free(ptr); } #endif /* MY_ZCALLOC */ #endif /* !Z_SOLO */ opengnb-ver1.6.0.a/libs/zlib/zutil.h000066400000000000000000000150251500454252100173140ustar00rootroot00000000000000/* zutil.h -- internal interface and configuration of the compression library * Copyright (C) 1995-2024 Jean-loup Gailly, Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ /* WARNING: this file should *not* be used by applications. It is part of the implementation of the compression library and is subject to change. Applications should only use zlib.h. */ /* @(#) $Id$ */ #ifndef ZUTIL_H #define ZUTIL_H #ifdef HAVE_HIDDEN # define ZLIB_INTERNAL __attribute__((visibility ("hidden"))) #else # define ZLIB_INTERNAL #endif #include "zlib.h" #if defined(STDC) && !defined(Z_SOLO) # if !(defined(_WIN32_WCE) && defined(_MSC_VER)) # include # endif # include # include #endif #ifndef local # define local static #endif /* since "static" is used to mean two completely different things in C, we define "local" for the non-static meaning of "static", for readability (compile with -Dlocal if your debugger can't find static symbols) */ typedef unsigned char uch; typedef uch FAR uchf; typedef unsigned short ush; typedef ush FAR ushf; typedef unsigned long ulg; #if !defined(Z_U8) && !defined(Z_SOLO) && defined(STDC) # include # if (ULONG_MAX == 0xffffffffffffffff) # define Z_U8 unsigned long # elif (ULLONG_MAX == 0xffffffffffffffff) # define Z_U8 unsigned long long # elif (UINT_MAX == 0xffffffffffffffff) # define Z_U8 unsigned # endif #endif extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ /* (size given to avoid silly warnings with Visual C++) */ #define ERR_MSG(err) z_errmsg[(err) < -6 || (err) > 2 ? 9 : 2 - (err)] #define ERR_RETURN(strm,err) \ return (strm->msg = ERR_MSG(err), (err)) /* To be used only when the state is known to be valid */ /* common constants */ #ifndef DEF_WBITS # define DEF_WBITS MAX_WBITS #endif /* default windowBits for decompression. MAX_WBITS is for compression only */ #if MAX_MEM_LEVEL >= 8 # define DEF_MEM_LEVEL 8 #else # define DEF_MEM_LEVEL MAX_MEM_LEVEL #endif /* default memLevel */ #define STORED_BLOCK 0 #define STATIC_TREES 1 #define DYN_TREES 2 /* The three kinds of block type */ #define MIN_MATCH 3 #define MAX_MATCH 258 /* The minimum and maximum match lengths */ #define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */ /* target dependencies */ #if defined(MSDOS) || (defined(WINDOWS) && !defined(WIN32)) # define OS_CODE 0x00 # ifndef Z_SOLO # if defined(__TURBOC__) || defined(__BORLANDC__) # if (__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__)) /* Allow compilation with ANSI keywords only enabled */ void _Cdecl farfree( void *block ); void *_Cdecl farmalloc( unsigned long nbytes ); # else # include # endif # else /* MSC or DJGPP */ # include # endif # endif #endif #ifdef AMIGA # define OS_CODE 1 #endif #if defined(VAXC) || defined(VMS) # define OS_CODE 2 # define F_OPEN(name, mode) \ fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512") #endif #ifdef __370__ # if __TARGET_LIB__ < 0x20000000 # define OS_CODE 4 # elif __TARGET_LIB__ < 0x40000000 # define OS_CODE 11 # else # define OS_CODE 8 # endif #endif #if defined(ATARI) || defined(atarist) # define OS_CODE 5 #endif #ifdef OS2 # define OS_CODE 6 # if defined(M_I86) && !defined(Z_SOLO) # include # endif #endif #if defined(MACOS) # define OS_CODE 7 #endif #ifdef __acorn # define OS_CODE 13 #endif #if defined(WIN32) && !defined(__CYGWIN__) # define OS_CODE 10 #endif #ifdef _BEOS_ # define OS_CODE 16 #endif #ifdef __TOS_OS400__ # define OS_CODE 18 #endif #ifdef __APPLE__ # define OS_CODE 19 #endif #if defined(__BORLANDC__) && !defined(MSDOS) #pragma warn -8004 #pragma warn -8008 #pragma warn -8066 #endif /* provide prototypes for these when building zlib without LFS */ #if !defined(_WIN32) && \ (!defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0) ZEXTERN uLong ZEXPORT adler32_combine64(uLong, uLong, z_off_t); ZEXTERN uLong ZEXPORT crc32_combine64(uLong, uLong, z_off_t); ZEXTERN uLong ZEXPORT crc32_combine_gen64(z_off_t); #endif /* common defaults */ #ifndef OS_CODE # define OS_CODE 3 /* assume Unix */ #endif #ifndef F_OPEN # define F_OPEN(name, mode) fopen((name), (mode)) #endif /* functions */ #if defined(pyr) || defined(Z_SOLO) # define NO_MEMCPY #endif #if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__) /* Use our own functions for small and medium model with MSC <= 5.0. * You may have to use the same strategy for Borland C (untested). * The __SC__ check is for Symantec. */ # define NO_MEMCPY #endif #if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY) # define HAVE_MEMCPY #endif #ifdef HAVE_MEMCPY # ifdef SMALL_MEDIUM /* MSDOS small or medium model */ # define zmemcpy _fmemcpy # define zmemcmp _fmemcmp # define zmemzero(dest, len) _fmemset(dest, 0, len) # else # define zmemcpy memcpy # define zmemcmp memcmp # define zmemzero(dest, len) memset(dest, 0, len) # endif #else void ZLIB_INTERNAL zmemcpy(Bytef* dest, const Bytef* source, uInt len); int ZLIB_INTERNAL zmemcmp(const Bytef* s1, const Bytef* s2, uInt len); void ZLIB_INTERNAL zmemzero(Bytef* dest, uInt len); #endif /* Diagnostic functions */ #ifdef ZLIB_DEBUG # include extern int ZLIB_INTERNAL z_verbose; extern void ZLIB_INTERNAL z_error(char *m); # define Assert(cond,msg) {if(!(cond)) z_error(msg);} # define Trace(x) {if (z_verbose>=0) fprintf x ;} # define Tracev(x) {if (z_verbose>0) fprintf x ;} # define Tracevv(x) {if (z_verbose>1) fprintf x ;} # define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;} # define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;} #else # define Assert(cond,msg) # define Trace(x) # define Tracev(x) # define Tracevv(x) # define Tracec(c,x) # define Tracecv(c,x) #endif #ifndef Z_SOLO voidpf ZLIB_INTERNAL zcalloc(voidpf opaque, unsigned items, unsigned size); void ZLIB_INTERNAL zcfree(voidpf opaque, voidpf ptr); #endif #define ZALLOC(strm, items, size) \ (*((strm)->zalloc))((strm)->opaque, (items), (size)) #define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr)) #define TRY_FREE(s, p) {if (p) ZFREE(s, p);} /* Reverse the bytes in a 32-bit value */ #define ZSWAP32(q) ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \ (((q) & 0xff00) << 8) + (((q) & 0xff) << 24)) #endif /* ZUTIL_H */ opengnb-ver1.6.0.a/scripts/000077500000000000000000000000001500454252100155675ustar00rootroot00000000000000opengnb-ver1.6.0.a/scripts/opengnb@.service000066400000000000000000000037011500454252100207020ustar00rootroot00000000000000######################### #(1)发行版软件包应该将此单元模板应放置在 /usr/lib/systemd/system/ 目录中 #(2)可以使用例如 systemctl start|stop opengnb@xxx.service 这样的命令启动/停止"xxx"服务实例("xxx"表示使用"/etc/opengnb/xxx"配置目录) #(3)可以使用例如 systemctl enable|disable opengnb@xxx.service 这样的命令开启/关闭"xxx"服务实例的自动启动 # 上述命令等价于创建/删除 /etc/systemd/system/multi-user.target.wants/opengnb@xxx.service 软连接(指向 /usr/lib/systemd/system/opengnb@.service ) #(4)配置目录的名称(也就是"/etc/opengnb/xxx"中的"xxx")只能使用ASCII字母/数字/下划线(也就是只能使用 "a-z" "A-Z" "0-9" "_" 字符) ######################### [Unit] Description="GNB NAT Traversal P2P VPN" Documentation=https://github.com/gnbdev/opengnb/blob/master/docs/gnb_config_manual_cn.md \ https://github.com/gnbdev/opengnb/blob/master/docs/gnb_user_manual_en.md \ https://github.com/gnbdev/opengnb/blob/master/README_EN.md \ https://github.com/gnbdev/opengnb/blob/master/README.md #开机时,确保在网络接通之后才会启动 Wants=network-online.target After=network-online.target #开机时,确保在DNS解析就绪之后才会启动 #Wants=nss-lookup.target #After=nss-lookup.target #关机时,确保在关闭网络之前已经停止 After=network.target [Service] #为兼容 systemd 老版本所做的妥协(v240 以上版本建议设置为 Type=exec ) Type=simple PIDFile=/run/opengnb-%I.pid ExecStartPre=/bin/mkdir -p /var/log/opengnb/%I ExecStartPre=/bin/mkdir -p /var/cache/opengnb ExecStart=/usr/sbin/gnb --systemd --conf=/etc/opengnb/%I --pid-file=/run/opengnb-%I.pid --ctl-block=/var/cache/opengnb/%I.map --node-cache-file=/var/cache/opengnb/%I.dump --log-file-path=/var/log/opengnb/%I --ifname=gnb_tun_%I [Install] WantedBy=multi-user.target #默认实例名称(仅当 systemctl enable 命令没有指定实例名称时有意义) DefaultInstance=default opengnb-ver1.6.0.a/src/000077500000000000000000000000001500454252100146675ustar00rootroot00000000000000opengnb-ver1.6.0.a/src/Darwin/000077500000000000000000000000001500454252100161135ustar00rootroot00000000000000opengnb-ver1.6.0.a/src/Darwin/gnb_drv_darwin.c000077500000000000000000000234701500454252100212550ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "gnb.h" #include "gnb_tun_drv.h" #include "gnb_payload16.h" void bind_socket_if(gnb_core_t *gnb_core){ if ( '\0' == gnb_core->conf->socket_ifname[0] ) { return; } int i; for ( i=0; i < gnb_core->conf->udp6_socket_num; i++ ) { setsockopt(gnb_core->udp_ipv6_sockets[i], SOL_SOCKET,IP_RECVIF, gnb_core->conf->socket_ifname, strlen(gnb_core->conf->socket_ifname)); } for ( i=0; i < gnb_core->conf->udp4_socket_num; i++ ) { setsockopt(gnb_core->udp_ipv4_sockets[i], SOL_SOCKET,IP_RECVIF, gnb_core->conf->socket_ifname, strlen(gnb_core->conf->socket_ifname)); } } static void if_up_script(gnb_core_t *gnb_core){ int ret; char cmd[1024]; snprintf(cmd,1024,"%s/scripts/%s > /dev/null 2>&1",gnb_core->conf->conf_dir,"if_up_darwin.sh"); ret = system(cmd); if ( -1==ret || 0==ret ) { return; } return; } static void if_down_script(gnb_core_t *gnb_core){ int ret; char cmd[1024]; snprintf(cmd,1024,"%s/scripts/%s > /dev/null 2>&1",gnb_core->conf->conf_dir,"if_down_darwin.sh"); ret = system(cmd); if ( -1==ret || 0==ret ) { return; } return; } /* set_route4的作用是 创建一条路由,以 tun ip 为 10.1.0.15 的local node为例: route -n add -net 10.1.0.0 -netmask 255.255.255.0 10.1.0.15 */ static void set_route4(gnb_core_t *gnb_core){ struct{ struct rt_msghdr hdr; struct sockaddr_in dst; struct sockaddr_in gateway; struct sockaddr_in mask; }rtmsg; uint32_t network_u32; int s; ssize_t wlen; //算出 节点的 ipv4 network network_u32 = gnb_core->local_node->tun_netmask_addr4.s_addr & gnb_core->local_node->tun_addr4.s_addr; s = socket(PF_ROUTE, SOCK_RAW, 0); if ( s < 0 ) { printf("error: socket\n"); return; } shutdown(s, SHUT_RD); bzero(&rtmsg, sizeof(rtmsg)); rtmsg.hdr.rtm_type = RTM_ADD; rtmsg.hdr.rtm_version = RTM_VERSION; rtmsg.hdr.rtm_addrs = 0; rtmsg.hdr.rtm_addrs |= RTA_DST; rtmsg.hdr.rtm_addrs |= RTA_GATEWAY; rtmsg.hdr.rtm_addrs |= RTA_NETMASK; rtmsg.hdr.rtm_flags = RTF_STATIC; rtmsg.hdr.rtm_flags |= RTF_GATEWAY; rtmsg.hdr.rtm_flags |= RTF_GATEWAY; rtmsg.dst.sin_len = sizeof(rtmsg.dst); rtmsg.dst.sin_family = AF_INET; rtmsg.dst.sin_addr.s_addr = network_u32; rtmsg.mask.sin_len = sizeof(rtmsg.mask); rtmsg.mask.sin_family = AF_INET; rtmsg.mask.sin_addr.s_addr = gnb_core->local_node->tun_netmask_addr4.s_addr; rtmsg.gateway.sin_len = sizeof(rtmsg.gateway); rtmsg.gateway.sin_family = AF_INET; rtmsg.gateway.sin_addr.s_addr = gnb_core->local_node->tun_addr4.s_addr; rtmsg.hdr.rtm_msglen = sizeof(rtmsg); wlen = write(s, &rtmsg, sizeof(rtmsg)); if ( -1==wlen ) { perror("#set_route4 write"); return; } return; } static int set_addr6(char *if_name, char *ip, char *netmask) { //不要设置 in6_addreq.ifra_dstaddr 成员, ioctl 会提示参数不正确 struct in6_aliasreq in6_addreq = { { 0 }, { 0 }, { 0 }, { 0 }, 0, { 0, 0, ND6_INFINITE_LIFETIME, ND6_INFINITE_LIFETIME } }; struct addrinfo *srcres, *netmaskres; struct addrinfo hints; bzero(&hints, sizeof(struct addrinfo)); hints.ai_family = AF_INET6; getaddrinfo(ip, NULL, &hints, &srcres); getaddrinfo(netmask, NULL, &hints, &netmaskres); strncpy(in6_addreq.ifra_name, if_name, IFNAMSIZ); memcpy(&in6_addreq.ifra_addr, srcres->ai_addr, srcres->ai_addr->sa_len); memcpy(&in6_addreq.ifra_prefixmask, netmaskres->ai_addr, netmaskres->ai_addr->sa_len); freeaddrinfo(srcres); freeaddrinfo(netmaskres); int socket_fd; if ( (socket_fd = socket(AF_INET6, SOCK_DGRAM, 0) ) < 0) { perror("socket "); return -1; } int ret = ioctl(socket_fd, SIOCAIFADDR_IN6, &in6_addreq); if ( -1 == ret ) { perror("ioctl"); } close(socket_fd); return ret; } static int tun_alloc(char *dev) { int fd; struct ctl_info ctlInfo; strncpy(ctlInfo.ctl_name, UTUN_CONTROL_NAME, sizeof(ctlInfo.ctl_name)); fd = socket(PF_SYSTEM, SOCK_DGRAM, SYSPROTO_CONTROL); if ( fd < 0 ) { perror("socket"); return fd; } struct sockaddr_ctl sc; if ( ioctl(fd, CTLIOCGINFO, &ctlInfo) == -1 ) { close(fd); perror("ioctl"); return -1; } sc.sc_id = ctlInfo.ctl_id; sc.sc_len = sizeof(sc); sc.sc_family = AF_SYSTEM; sc.ss_sysaddr = AF_SYS_CONTROL; //sc.sc_unit = 1; // faile //sc.sc_unit = 10; // ok sc.sc_unit = 0; // ok if ( connect(fd, (struct sockaddr *)&sc, sizeof(sc)) < 0 ) { perror("connect"); close(fd); return -1; } return fd; } int init_tun_darwin(gnb_core_t *gnb_core){ gnb_core->tun_fd = -1; return 0; } static void setifmtu(char *if_name,int mtu) { int socket_fd; struct ifreq ifr; memset(&ifr,0,sizeof(struct ifreq)); strncpy(ifr.ifr_name, if_name, IFNAMSIZ); ifr.ifr_mtu = mtu; if ( (socket_fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) { perror("socket "); } int ret = ioctl(socket_fd, SIOCSIFMTU, &ifr); if ( -1 == ret ) { perror("ioctl"); } close(socket_fd); } static int set_addr4(char *if_name, char *ip, char *netmask) { struct addrinfo *srcres, *dstres, *netmaskres; struct ifaliasreq in_addreq; memset(&in_addreq, 0, sizeof(in_addreq)); getaddrinfo(ip, NULL, NULL, &srcres); getaddrinfo(ip, NULL, NULL, &dstres); getaddrinfo(netmask, NULL, NULL, &netmaskres); strncpy(in_addreq.ifra_name, if_name, IFNAMSIZ); memcpy(&in_addreq.ifra_addr, srcres->ai_addr, srcres->ai_addr->sa_len); memcpy(&in_addreq.ifra_dstaddr, dstres->ai_addr, dstres->ai_addr->sa_len); memcpy(&in_addreq.ifra_mask, netmaskres->ai_addr, netmaskres->ai_addr->sa_len); freeaddrinfo(srcres); freeaddrinfo(dstres); freeaddrinfo(netmaskres); int socket_fd; if ( (socket_fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) { perror("socket "); return -1; } int ret = ioctl(socket_fd, SIOCAIFADDR, &in_addreq); if ( -1 == ret ) { perror("ioctl"); } return 0; } static int open_tun_darwin(gnb_core_t *gnb_core){ if ( -1 != gnb_core->tun_fd ) { return -1; } gnb_core->tun_fd = tun_alloc(gnb_core->ifname); memset(gnb_core->ifname,0,IFNAMSIZ); socklen_t ifname_len = IFNAMSIZ; getsockopt (gnb_core->tun_fd, SYSPROTO_CONTROL, UTUN_OPT_IFNAME, gnb_core->ifname, &ifname_len); set_addr4(gnb_core->ifname, GNB_ADDR4STR_PLAINTEXT1(&gnb_core->local_node->tun_addr4), GNB_ADDR4STR_PLAINTEXT2(&gnb_core->local_node->tun_netmask_addr4)); set_addr6(gnb_core->ifname, GNB_ADDR6STR_PLAINTEXT1(&gnb_core->local_node->tun_ipv6_addr), "FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:0000:0000"); set_route4(gnb_core); setifmtu(gnb_core->ifname, gnb_core->conf->mtu); if_up_script(gnb_core); return 0; } static int read_tun_darwin(gnb_core_t *gnb_core, void *buf, size_t buf_size){ ssize_t rlen; u_int32_t type; struct iovec iv[2]; struct ip *iph; iph = (struct ip *) buf; if ( 6 == iph->ip_v ) { type = htonl(AF_INET6); } else { type = htonl(AF_INET); } iv[0].iov_base = (char *)&type; iv[0].iov_len = sizeof (type); iv[1].iov_base = buf; iv[1].iov_len = buf_size; rlen = readv(gnb_core->tun_fd, iv, 2); if ( -1 == rlen ) { return rlen; } if ( rlen - sizeof(u_int32_t) <=0 ) { return -1; } return rlen - sizeof(u_int32_t); } static int write_tun_darwin(gnb_core_t *gnb_core, void *buf, size_t buf_size){ u_int32_t type; struct iovec iv[2]; struct ip *iph; iph = (struct ip *) buf; if ( 6 == iph->ip_v ) { type = htonl(AF_INET6); } else { type = htonl(AF_INET); } iv[0].iov_base = (char *)&type; iv[0].iov_len = sizeof (type); iv[1].iov_base = buf; iv[1].iov_len = buf_size; writev(gnb_core->tun_fd, iv, 2); return 0; } static int close_tun_darwin(gnb_core_t *gnb_core){ if_down_script(gnb_core); close(gnb_core->tun_fd); return 0; } static int release_tun_darwin(gnb_core_t *gnb_core){ return 0; } gnb_tun_drv_t gnb_tun_drv_darwin = { init_tun_darwin, open_tun_darwin, read_tun_darwin, write_tun_darwin, close_tun_darwin, release_tun_darwin }; opengnb-ver1.6.0.a/src/cli/000077500000000000000000000000001500454252100154365ustar00rootroot00000000000000opengnb-ver1.6.0.a/src/cli/gnb.c000077500000000000000000000350531500454252100163610ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 #include #include #include #include #include "gnb.h" #include "gnb_core.h" #include "gnb_time.h" #include "gnb_address.h" #include "gnb_arg_list.h" #include "gnb_conf_file.h" #include "gnb_log.h" #ifdef _WIN32 #include #endif #ifndef GNB_SKIP_BUILD_TIME #define GNB_BUILD_STRING "Build Time ["__DATE__","__TIME__"]" #else #define GNB_BUILD_STRING "Build Time [Hidden]" #endif gnb_core_t *gnb_core; int gnb_daemon(); void save_pid(const char *pid_file); gnb_conf_t* gnb_argv(int argc,char *argv[]); void primary_process_loop(gnb_core_t *gnb_core); extern gnb_pf_t *gnb_pf_mods[]; extern gnb_arg_list_t *gnb_es_arg_list; extern int is_self_test; void signal_alrm_handler(int signum){ return; } void signal_handler(int signum){ if ( SIGTERM == signum ) { goto finish; } if ( SIGINT == signum ) { goto finish; } finish: gnb_core_stop(gnb_core); unlink(gnb_core->conf->pid_file); exit(0); } static void self_test(){ int i; int j; int node_num; gnb_ctl_block_t *ctl_block; gnb_address_list_t *static_address_list; gnb_address_t *gnb_address; gnb_node_t *node; int ret; char es_arg_string[GNB_ARG_STRING_MAX_SIZE]; GNB_LOG1(gnb_core->log, GNB_LOG_ID_CORE, "SELF-TEST daemon='%d'\n", gnb_core->conf->daemon ); GNB_LOG1(gnb_core->log, GNB_LOG_ID_CORE, "SELF-TEST systemd_daemon='%d'\n", gnb_core->conf->systemd_daemon ); if ( 1 == gnb_core->conf->activate_tun && 0 == gnb_core->conf->public_index_service ) { GNB_LOG1(gnb_core->log, GNB_LOG_ID_CORE, "SELF-TEST local node=%lu\n", gnb_core->local_node->uuid64); GNB_LOG1(gnb_core->log, GNB_LOG_ID_CORE, "SELF-TEST tun ipv4[%s]\n", GNB_ADDR4STR_PLAINTEXT1(&gnb_core->local_node->tun_addr4)); } GNB_LOG1(gnb_core->log, GNB_LOG_ID_CORE, "SELF-TEST binary_dir='%s'\n", gnb_core->conf->binary_dir); GNB_LOG1(gnb_core->log, GNB_LOG_ID_CORE, "SELF-TEST conf_dir='%s'\n", gnb_core->conf->conf_dir); GNB_LOG1(gnb_core->log, GNB_LOG_ID_CORE, "SELF-TEST map_file='%s'\n", gnb_core->conf->map_file); GNB_LOG1(gnb_core->log, GNB_LOG_ID_CORE, "SELF-TEST pid_file='%s'\n", gnb_core->conf->pid_file); GNB_LOG1(gnb_core->log, GNB_LOG_ID_CORE, "SELF-TEST log_path='%s'\n", gnb_core->conf->log_path); GNB_LOG1(gnb_core->log, GNB_LOG_ID_CORE, "SELF-TEST node_cache_file='%s'\n", gnb_core->conf->node_cache_file); GNB_LOG1(gnb_core->log, GNB_LOG_ID_CORE, "SELF-TEST listen='%s'\n", gnb_core->conf->listen_address6_string); GNB_LOG1(gnb_core->log, GNB_LOG_ID_CORE, "SELF-TEST listen6='%s'\n", gnb_core->conf->listen_address4_string); GNB_LOG1(gnb_core->log, GNB_LOG_ID_CORE, "SELF-TEST mtu=%d\n", gnb_core->conf->mtu); GNB_LOG1(gnb_core->log, GNB_LOG_ID_CORE, "SELF-TEST addr_secure=%d\n", gnb_core->conf->addr_secure); GNB_LOG1(gnb_core->log, GNB_LOG_ID_CORE, "SELF-TEST lite_mode=%d\n", gnb_core->conf->lite_mode); GNB_LOG1(gnb_core->log, GNB_LOG_ID_CORE, "SELF-TEST public_index_service=%d\n", gnb_core->conf->public_index_service); GNB_LOG1(gnb_core->log, GNB_LOG_ID_CORE, "SELF-TEST multi_socket=%d\n", gnb_core->conf->multi_socket); GNB_LOG1(gnb_core->log, GNB_LOG_ID_CORE, "SELF-TEST direct_forwarding=%d\n", gnb_core->conf->direct_forwarding); GNB_LOG1(gnb_core->log, GNB_LOG_ID_CORE, "SELF-TEST pf_worker_num=%d\n", gnb_core->conf->pf_worker_num); switch (gnb_core->conf->memory) { case GNB_MEMORY_SCALE_TINY: GNB_LOG1(gnb_core->log, GNB_LOG_ID_CORE, "SELF-TEST memory scale tiny\n"); break; case GNB_MEMORY_SCALE_SMALL: GNB_LOG1(gnb_core->log, GNB_LOG_ID_CORE, "SELF-TEST memory scale samll\n"); break; case GNB_MEMORY_SCALE_LARGE: GNB_LOG1(gnb_core->log, GNB_LOG_ID_CORE, "SELF-TEST memory scale lage\n"); break; case GNB_MEMORY_SCALE_HUGE: GNB_LOG1(gnb_core->log, GNB_LOG_ID_CORE, "SELF-TEST memory scale huge\n"); break; default: GNB_LOG1(gnb_core->log, GNB_LOG_ID_CORE, "SELF-TEST memory scale error\n"); break; } switch (gnb_core->conf->zip) { case GNB_ZIP_AUTO: GNB_LOG1(gnb_core->log, GNB_LOG_ID_CORE, "SELF-TEST zip auto\n"); break; case GNB_ZIP_FORCE: GNB_LOG1(gnb_core->log, GNB_LOG_ID_CORE, "SELF-TEST zip force\n"); break; default: GNB_LOG1(gnb_core->log, GNB_LOG_ID_CORE, "SELF-TEST zip config error\n"); break; } GNB_LOG1(gnb_core->log, GNB_LOG_ID_CORE, "SELF-TEST zip_level=%d\n", gnb_core->conf->zip_level); if ( GNB_PF_BITS_NONE == gnb_core->conf->pf_bits ) { GNB_LOG1(gnb_core->log, GNB_LOG_ID_CORE, "SELF-TEST crypto none\n"); } if ( gnb_core->conf->pf_bits & GNB_PF_BITS_CRYPTO_XOR ) { GNB_LOG1(gnb_core->log, GNB_LOG_ID_CORE, "SELF-TEST crypto xor\n"); } if ( gnb_core->conf->pf_bits & GNB_PF_BITS_CRYPTO_ARC4 ) { GNB_LOG1(gnb_core->log, GNB_LOG_ID_CORE, "SELF-TEST crypto arc4\n"); } switch (gnb_core->conf->unified_forwarding) { case GNB_UNIFIED_FORWARDING_OFF: GNB_LOG1(gnb_core->log, GNB_LOG_ID_CORE, "SELF-TEST unified_forwarding=off\n"); break; case GNB_UNIFIED_FORWARDING_FORCE: GNB_LOG1(gnb_core->log, GNB_LOG_ID_CORE, "SELF-TEST unified_forwarding=force\n"); break; case GNB_UNIFIED_FORWARDING_AUTO: GNB_LOG1(gnb_core->log, GNB_LOG_ID_CORE, "SELF-TEST unified_forwarding=auto\n"); break; case GNB_UNIFIED_FORWARDING_SUPER: GNB_LOG1(gnb_core->log, GNB_LOG_ID_CORE, "SELF-TEST unified_forwarding=super\n"); break; case GNB_UNIFIED_FORWARDING_HYPER: GNB_LOG1(gnb_core->log, GNB_LOG_ID_CORE, "SELF-TEST unified_forwarding=hyper\n"); break; default: GNB_LOG1(gnb_core->log, GNB_LOG_ID_CORE, "SELF-TEST unified_forwarding config error\n"); break; } GNB_LOG1(gnb_core->log, GNB_LOG_ID_CORE, "SELF-TEST activate tun=%d\n", gnb_core->conf->activate_tun); GNB_LOG1(gnb_core->log, GNB_LOG_ID_CORE, "SELF-TEST universal relay0 ur0=%d\n", gnb_core->conf->universal_relay0); GNB_LOG1(gnb_core->log, GNB_LOG_ID_CORE, "SELF-TEST universal relay1 ur1=%d\n", gnb_core->conf->universal_relay1); GNB_LOG1(gnb_core->log, GNB_LOG_ID_CORE, "SELF-TEST console_log_level=%d\n", gnb_core->conf->console_log_level); GNB_LOG1(gnb_core->log, GNB_LOG_ID_CORE, "SELF-TEST file_log_level=%d\n", gnb_core->conf->file_log_level); GNB_LOG1(gnb_core->log, GNB_LOG_ID_CORE, "SELF-TEST udp_log_level=%d\n", gnb_core->conf->udp_log_level); GNB_LOG1(gnb_core->log, GNB_LOG_ID_CORE, "SELF-TEST log_udp_type=%d\n", gnb_core->conf->log_udp_type); GNB_LOG1(gnb_core->log, GNB_LOG_ID_CORE, "SELF-TEST GNB_LOG_ID_CORE console_level=%d, file_level=%d, udp_level=%d\n", gnb_core->log->config_table[GNB_LOG_ID_CORE].console_level, gnb_core->log->config_table[GNB_LOG_ID_CORE].file_level, gnb_core->log->config_table[GNB_LOG_ID_CORE].udp_level); GNB_LOG1(gnb_core->log, GNB_LOG_ID_CORE, "SELF-TEST GNB_LOG_ID_PF console_level=%d, file_level=%d, udp_level=%d\n", gnb_core->log->config_table[GNB_LOG_ID_PF].console_level, gnb_core->log->config_table[GNB_LOG_ID_PF].file_level, gnb_core->log->config_table[GNB_LOG_ID_PF].udp_level); GNB_LOG1(gnb_core->log, GNB_LOG_ID_CORE, "SELF-TEST GNB_LOG_ID_MAIN_WORKER console_level=%d,file_level=%d, udp_level=%d\n", gnb_core->log->config_table[GNB_LOG_ID_MAIN_WORKER].console_level, gnb_core->log->config_table[GNB_LOG_ID_MAIN_WORKER].file_level, gnb_core->log->config_table[GNB_LOG_ID_MAIN_WORKER].udp_level); GNB_LOG1(gnb_core->log, GNB_LOG_ID_CORE, "SELF-TEST GNB_LOG_ID_NODE_WORKER console_level=%d, file_level=%d, udp_level=%d\n", gnb_core->log->config_table[GNB_LOG_ID_NODE_WORKER].console_level, gnb_core->log->config_table[GNB_LOG_ID_NODE_WORKER].file_level, gnb_core->log->config_table[GNB_LOG_ID_NODE_WORKER].udp_level); GNB_LOG1(gnb_core->log, GNB_LOG_ID_CORE, "SELF-TEST GNB_LOG_ID_INDEX_WORKER console_level=%d, file_level=%d, udp_level=%d\n", gnb_core->log->config_table[GNB_LOG_ID_INDEX_WORKER].console_level, gnb_core->log->config_table[GNB_LOG_ID_INDEX_WORKER].file_level, gnb_core->log->config_table[GNB_LOG_ID_INDEX_WORKER].udp_level); GNB_LOG1(gnb_core->log, GNB_LOG_ID_CORE, "SELF-TEST GNB_LOG_ID_INDEX_SERVICE_WORKER console_level=%d, file_level=%d, udp_level=%d\n", gnb_core->log->config_table[GNB_LOG_ID_INDEX_SERVICE_WORKER].console_level, gnb_core->log->config_table[GNB_LOG_ID_INDEX_SERVICE_WORKER].file_level, gnb_core->log->config_table[GNB_LOG_ID_INDEX_SERVICE_WORKER].udp_level); GNB_LOG1(gnb_core->log, GNB_LOG_ID_CORE, "SELF-TEST GNB_LOG_ID_DETECT_WORKER console_level=%d, file_level=%d, udp_level=%d\n", gnb_core->log->config_table[GNB_LOG_ID_DETECT_WORKER].console_level, gnb_core->log->config_table[GNB_LOG_ID_DETECT_WORKER].file_level, gnb_core->log->config_table[GNB_LOG_ID_DETECT_WORKER].udp_level); if ( 1 == gnb_core->conf->activate_tun && 0 == gnb_core->conf->public_index_service ) { ctl_block = gnb_core->ctl_block; node_num = ctl_block->node_zone->node_num; for ( i=0; inode_zone->node[i]; if ( node->uuid64 != ctl_block->core_zone->local_uuid ) { GNB_LOG1(gnb_core->log, GNB_LOG_ID_CORE, "SELF-TEST ----- remote node %llu -----\n", node->uuid64); } else { GNB_LOG1(gnb_core->log, GNB_LOG_ID_CORE, "SELF-TEST local node %llu\n", node->uuid64); } GNB_LOG1(gnb_core->log, GNB_LOG_ID_CORE, "SELF-TEST tun_ipv6 %s\n", GNB_ADDR6STR_PLAINTEXT1(&node->tun_ipv6_addr)); GNB_LOG1(gnb_core->log, GNB_LOG_ID_CORE, "SELF-TEST tun_ipv4 %s\n", GNB_ADDR4STR_PLAINTEXT1(&node->tun_addr4)); static_address_list = (gnb_address_list_t *)&node->static_address_block; for ( j=0; jnum; j++ ) { gnb_address = &static_address_list->array[j]; if ( 0 == gnb_address->port ) { continue; } GNB_LOG1(gnb_core->log, GNB_LOG_ID_CORE,"SELF-TEST address %s\n", GNB_IP_PORT_STR1(gnb_address)); } } GNB_LOG1(gnb_core->log, GNB_LOG_ID_CORE, "SELF-TEST num of index=%d\n", gnb_core->index_address_ring.address_list->num); for ( i=0; i< gnb_core->index_address_ring.address_list->num; i++ ) { GNB_LOG1(gnb_core->log, GNB_LOG_ID_CORE, "SELF-TEST index node '%s'\n", GNB_IP_PORT_STR1(&gnb_core->index_address_ring.address_list->array[i])); } GNB_LOG1(gnb_core->log, GNB_LOG_ID_CORE,"SELF-TEST num of fwd node:%d\n", gnb_core->fwd_node_ring.num); for ( i=0; ifwd_node_ring.num; i++ ) { GNB_LOG1(gnb_core->log, GNB_LOG_ID_CORE, "SELF-TEST fwd node=%llu\n", gnb_core->fwd_node_ring.nodes[i]->uuid64); } for ( i=0; iargc; i++ ) { GNB_LOG1(gnb_core->log, GNB_LOG_ID_CORE, "SELF-TEST gnb_es argv[%d]='%s'\n", i, gnb_es_arg_list->argv[i]); } ret = gnb_arg_list_to_string(gnb_es_arg_list, es_arg_string, GNB_ARG_STRING_MAX_SIZE); if ( 0 == ret ) { GNB_LOG1(gnb_core->log, GNB_LOG_ID_CORE, "SELF-TEST exec gnb_es argv '%s'\n", es_arg_string); } else { GNB_LOG1(gnb_core->log, GNB_LOG_ID_CORE, "SELF-TEST will not exec 'gnb_es'\n"); } } } #ifdef _WIN32 BOOL CALLBACK CosonleHandler(DWORD ev) { switch (ev) { case CTRL_CLOSE_EVENT: case CTRL_C_EVENT: gnb_core_stop(gnb_core); exit(0); default: exit(0); break; } return TRUE; } #endif void log_out_description(gnb_log_ctx_t *log){ GNB_LOG1(log, GNB_LOG_ID_CORE, "%s\n", GNB_VERSION_STRING); GNB_LOG1(log, GNB_LOG_ID_CORE, "%s\n", GNB_COPYRIGHT_STRING); GNB_LOG1(log, GNB_LOG_ID_CORE, "Site: %s\n", GNB_URL_STRING); GNB_LOG1(log, GNB_LOG_ID_CORE, "%s\n", GNB_BUILD_STRING); } void show_description(){ printf("%s\n", GNB_VERSION_STRING); printf("%s\n", GNB_COPYRIGHT_STRING); printf("Site: %s\n", GNB_URL_STRING); int idx = 0; printf("registered packet filter:"); while ( NULL != gnb_pf_mods[idx] ) { printf(" %s", gnb_pf_mods[idx]->name); idx++; } printf("\n"); printf("%s\n", GNB_BUILD_STRING); } int main (int argc,char *argv[]){ gnb_conf_t *conf; int pid; int ret; setvbuf(stdout,NULL,_IOLBF,0); #ifdef _WIN32 WSADATA wsaData; int err; err = WSAStartup(MAKEWORD(2, 2), &wsaData ); SetConsoleCtrlHandler(CosonleHandler, TRUE); #endif conf = gnb_argv(argc, argv); if ( 0 == conf->public_index_service ) { if ( 0 == conf->lite_mode ) { //加载 node.conf local_node_file_config(conf); } gnb_core = gnb_core_create(conf); } else { gnb_core = gnb_core_index_service_create(conf); } free(conf); if ( NULL == gnb_core ) { printf("gnb core create error!\n"); return 1; } GNB_LOG1(gnb_core->log, GNB_LOG_ID_CORE, "gnb core created!\n"); #ifdef __UNIX_LIKE_OS__ signal(SIGPIPE, SIG_IGN); signal(SIGALRM, signal_alrm_handler); signal(SIGTERM, signal_handler); signal(SIGINT, signal_handler); if ( gnb_core->conf->daemon ) { gnb_daemon(); } save_pid(gnb_core->conf->pid_file); #endif ret = gettimeofday(&gnb_core->now_timeval,NULL); gnb_core->now_time_sec = gnb_core->now_timeval.tv_sec; gnb_core->now_time_usec = gnb_core->now_timeval.tv_sec * 1000000 + gnb_core->now_timeval.tv_usec; if ( 1 == is_self_test ) { self_test(); } if ( 0 == gnb_core->conf->public_index_service ) { gnb_core_start(gnb_core); } else { gnb_core_index_service_start(gnb_core); } primary_process_loop(gnb_core); #ifdef _WIN32 WSACleanup(); #endif return 0; } opengnb-ver1.6.0.a/src/cli/gnb_crypto.c000077500000000000000000000073151500454252100177610ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 #include #include #include #include #include #include #include #include #include "gnb.h" #include "gnb_keys.h" #include "gnb_binary.h" #include "crypto/random/gnb_random.h" #include "ed25519/ed25519.h" #ifndef GNB_SKIP_BUILD_TIME #define GNB_BUILD_STRING "Build Time ["__DATE__","__TIME__"]" #else #define GNB_BUILD_STRING "Build Time [Hidden]" #endif static void show_useage(int argc,char *argv[]){ printf("%s\n", GNB_BUILD_STRING); printf("usage: %s -c -p private_key_file -k public_key_file\n",argv[0]); printf("example:\n"); printf("%s -c -p 1001.private -k 1001.public\n",argv[0]); } static void create_keypair(gnb_uuid_t uuid64, const char *private_key_file, const char *public_key_file){ int private_file_fd; int public_file_fd; unsigned char seed[32]; unsigned char ed25519_private_key[64]; unsigned char ed25519_public_key[32]; char hex_string[128]; void *p; ssize_t rlen; ssize_t wlen; gnb_random_data(seed, 32); ed25519_create_keypair(ed25519_public_key, ed25519_private_key, (const unsigned char *)seed); gnb_bin2hex(ed25519_public_key, 32, hex_string); public_file_fd = open(public_key_file, O_WRONLY|O_CREAT,S_IRUSR|S_IWUSR); if ( -1 == public_file_fd ) { perror("create public key file"); exit(0); } wlen = write(public_file_fd,hex_string,64); if ( -1 == wlen ) { perror("write public key file"); } close(public_file_fd); gnb_bin2hex(ed25519_private_key, 64, hex_string); private_file_fd = open(private_key_file, O_WRONLY|O_CREAT,S_IRUSR|S_IWUSR); if ( -1 == private_file_fd ) { perror("create private key file"); exit(0); } wlen = write(private_file_fd,hex_string,128); if ( -1 == wlen ) { perror("write private key file"); } close(private_file_fd); } int main (int argc,char *argv[]){ static struct option long_options[] = { { "create", required_argument, 0, 'c' }, { "private_key", required_argument, 0, 'p' }, { "public_key", required_argument, 0, 'k' }, { 0, 0, 0, 0 } }; int opt; gnb_uuid_t uuid64 = 0; char *public_key_file = NULL; char *private_key_file = NULL; char *cmd = NULL; while (1) { int option_index = 0; opt = getopt_long (argc, argv, "ck:p:h",long_options, &option_index); if ( -1 == opt ) { break; } switch (opt) { case 'c': cmd = "create"; break; case 'p': private_key_file = optarg; break; case 'k': public_key_file = optarg; break; case 'h': break; default: break; } } if ( NULL==cmd || NULL==private_key_file || NULL==public_key_file ) { show_useage(argc, argv); exit(0); } create_keypair(uuid64, private_key_file, public_key_file); return 0; } opengnb-ver1.6.0.a/src/cli/gnb_ctl.c000077500000000000000000000102761500454252100172230ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 #include #include #include #include #include #ifdef _WIN32 #include #include #include #endif #include "gnb_conf_type.h" #include "gnb_ctl_block.h" #ifndef GNB_SKIP_BUILD_TIME #define GNB_BUILD_STRING "Build Time ["__DATE__","__TIME__"]" #else #define GNB_BUILD_STRING "Build Time [Hidden]" #endif void gnb_ctl_dump_status(gnb_ctl_block_t *ctl_block, gnb_uuid_t in_nodeid, uint8_t online_opt); void gnb_ctl_dump_address_list(gnb_ctl_block_t *ctl_block, gnb_uuid_t in_nodeid, uint8_t online_opt); static void show_useage(int argc,char *argv[]){ printf("GNB Ctl version 1.6.0.a protocol version 1.6.0\n"); printf("%s\n", GNB_BUILD_STRING); printf("Copyright (C) 2019 gnbdev\n"); printf("Usage: %s -b CTL_BLOCK [OPTION]\n", argv[0]); printf("Command Summary:\n"); printf(" -b, --ctl-block ctl block mapper file\n"); printf(" -c, --core operate core zone\n"); printf(" -a, --address dunmp address\n"); printf(" -s, --status dunmp node status\n"); printf(" -o, --online dunmp online node\n"); printf(" -n, --node node id\n"); printf(" --help\n"); printf("example:\n"); printf("%s -b gnb.map -c -s\n",argv[0]); } int main (int argc,char *argv[]){ char *ctl_block_file = NULL; gnb_ctl_block_t *ctl_block; uint8_t address_opt = 0; uint8_t core_opt = 0; uint8_t node_status_opt = 0; uint8_t online_opt = 0; gnb_uuid_t nodeid = 0; static struct option long_options[] = { { "ctl-block", required_argument, 0, 'b' }, { "node", required_argument, 0, 'n' }, { "core", no_argument, 0, 'c' }, { "status", no_argument, 0, 's' }, { "address", no_argument, 0, 'a' }, { "online", no_argument, 0, 'o' }, { "help", no_argument, 0, 'h' }, { 0, 0, 0, 0 } }; setvbuf(stdout,NULL,_IOLBF,0); int opt; while (1) { int option_index = 0; opt = getopt_long (argc, argv, "b:n:csaoh",long_options, &option_index); if ( opt == -1 ) { break; } switch (opt) { case 'b': ctl_block_file = optarg; break; case 'n': nodeid = (gnb_uuid_t)strtoull(optarg, NULL, 10); break; case 'c': core_opt = 1; break; case 's': node_status_opt = 1; break; case 'a': address_opt = 1; break; case 'o': online_opt = 1; break; case 'h': show_useage(argc,argv); exit(0); default: break; } } if ( NULL == ctl_block_file ) { show_useage(argc,argv); exit(0); } ctl_block = gnb_get_ctl_block(ctl_block_file, 0); if ( NULL==ctl_block ) { printf("open ctl block error [%s]\n",ctl_block_file); exit(0); } #ifdef _WIN32 WSADATA wsaData; int err; err = WSAStartup(MAKEWORD(2, 2), &wsaData ); #endif if ( node_status_opt ) { gnb_ctl_dump_status(ctl_block, nodeid, online_opt); } if ( address_opt ) { gnb_ctl_dump_address_list(ctl_block, nodeid, online_opt); } #ifdef _WIN32 WSACleanup(); #endif return 0; } opengnb-ver1.6.0.a/src/cli/gnb_es.c000077500000000000000000000326511500454252100170510ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 #include #include #include #include #include #ifdef _WIN32 #include #include #include #endif #include "gnb_platform.h" #include "gnb_dir.h" #include "gnb_log.h" #include "gnb_conf_type.h" #include "gnb_ctl_block.h" #include "gnb_core_frame_type_defs.h" #include "es/gnb_es_type.h" #ifndef GNB_SKIP_BUILD_TIME #define GNB_BUILD_STRING "Build Time ["__DATE__","__TIME__"]" #else #define GNB_BUILD_STRING "Build Time [Hidden]" #endif gnb_es_ctx* gnb_es_ctx_create(int is_service, char *ctl_block_file,gnb_log_ctx_t *log); void gnb_es_ctx_init(gnb_es_ctx *es_ctx); int gnb_daemon(); void save_pid(const char *pid_file); #define GNB_ES_OPT_INIT 0x91 #define OPT_UPNP (GNB_ES_OPT_INIT + 1) #define OPT_UPNP_MULTICAST_IF (GNB_ES_OPT_INIT + 2) #define OPT_UPNP_GATEWAY4 (GNB_ES_OPT_INIT + 3) #define OPT_RESOLV (GNB_ES_OPT_INIT + 4) #define OPT_NOTIFY_ADDRESS (GNB_ES_OPT_INIT + 5) #define OPT_DUMP_ADDRESS (GNB_ES_OPT_INIT + 6) #define OPT_IF_UP (GNB_ES_OPT_INIT + 7) #define OPT_IF_DOWN (GNB_ES_OPT_INIT + 8) #define OPT_IF_LOOP (GNB_ES_OPT_INIT + 9) #define PID_FILE (GNB_ES_OPT_INIT + 10) #define WAN_ADDRESS6_FILE (GNB_ES_OPT_INIT + 11) #define LOG_UDP6 (GNB_ES_OPT_INIT + 12) #define LOG_UDP4 (GNB_ES_OPT_INIT + 13) #define LOG_UDP_TYPE (GNB_ES_OPT_INIT + 14) void gnb_start_environment_service(gnb_es_ctx *es_ctx); static void show_useage(int argc,char *argv[]){ printf("GNB Environment Service version 1.6.0.a protocol version 1.6.0\n"); printf("%s\n", GNB_BUILD_STRING); printf("Copyright (C) 2019 gnbdev\n"); printf("Usage: %s -b CTL_BLOCK [OPTION]\n", argv[0]); printf("Command Summary:\n"); printf(" -b, --ctl-block ctl block mapper file\n"); printf(" -s, --service service mode\n"); printf(" -d, --daemon daemon\n"); printf(" -L, --discover-in-lan discover in lan\n"); printf(" --upnp upnp\n"); printf(" --upnp-multicase-if upnp multicase interface\n"); printf(" --upnp-gateway4 upnp gateway ipv4 address\n"); printf(" --resolv resolv\n"); printf(" --dump-address dump address\n"); printf(" --notify-address notify address\n"); printf(" --pid-file pid file\n"); printf(" --wan-address6-file wan address6 file\n"); printf(" --if-up call at interface up\n"); printf(" --if-down call at interface down\n"); printf(" --if-loop call at interface loop\n"); printf(" --log-udp4 send log to the address ipv4 default is '127.0.0.1:8666'\n"); printf(" --log-udp-type the log udp type 'binary' or 'text' default is 'text'\n"); printf(" --help\n"); printf("example:\n"); printf("%s --ctl-block=./gnb.map -s --upnp\n",argv[0]); printf("%s --ctl-block=./gnb.map -s --resolv\n",argv[0]); } static void setup_log_ctx(gnb_log_ctx_t *log_ctx, char *log_udp_sockaddress4_string, uint8_t log_udp_type){ int rc; log_ctx->output_type = GNB_LOG_OUTPUT_STDOUT; snprintf(log_ctx->config_table[GNB_LOG_ID_ES_CORE].log_name, 20, "ES_CORE"); log_ctx->config_table[GNB_LOG_ID_ES_CORE].console_level = GNB_LOG_LEVEL1; log_ctx->config_table[GNB_LOG_ID_ES_CORE].file_level = GNB_LOG_LEVEL1; log_ctx->config_table[GNB_LOG_ID_ES_CORE].udp_level = GNB_LOG_LEVEL1; snprintf(log_ctx->config_table[GNB_LOG_ID_ES_UPNP].log_name, 20, "ES_UPNP"); log_ctx->config_table[GNB_LOG_ID_ES_UPNP].console_level = GNB_LOG_LEVEL1; log_ctx->config_table[GNB_LOG_ID_ES_UPNP].file_level = GNB_LOG_LEVEL1; log_ctx->config_table[GNB_LOG_ID_ES_UPNP].udp_level = GNB_LOG_LEVEL1; snprintf(log_ctx->config_table[GNB_LOG_ID_ES_RESOLV].log_name, 20, "ES_RESOLV"); log_ctx->config_table[GNB_LOG_ID_ES_RESOLV].console_level = GNB_LOG_LEVEL1; log_ctx->config_table[GNB_LOG_ID_ES_RESOLV].file_level = GNB_LOG_LEVEL1; log_ctx->config_table[GNB_LOG_ID_ES_RESOLV].udp_level = GNB_LOG_LEVEL1; snprintf(log_ctx->config_table[GNB_LOG_ID_ES_BROADCAST].log_name, 20, "ES_BROADCAST"); log_ctx->config_table[GNB_LOG_ID_ES_BROADCAST].console_level = GNB_LOG_LEVEL1; log_ctx->config_table[GNB_LOG_ID_ES_BROADCAST].file_level = GNB_LOG_LEVEL1; log_ctx->config_table[GNB_LOG_ID_ES_BROADCAST].udp_level = GNB_LOG_LEVEL1; snprintf(log_ctx->config_table[GNB_LOG_ID_ES_DISCOVER_IN_LAN].log_name, 20, "ES_DISCOVER_IN_LAN"); log_ctx->config_table[GNB_LOG_ID_ES_DISCOVER_IN_LAN].console_level = GNB_LOG_LEVEL1; log_ctx->config_table[GNB_LOG_ID_ES_DISCOVER_IN_LAN].file_level = GNB_LOG_LEVEL1; log_ctx->config_table[GNB_LOG_ID_ES_DISCOVER_IN_LAN].udp_level = GNB_LOG_LEVEL1; gnb_log_udp_open(log_ctx); log_ctx->log_udp_type = log_udp_type; log_ctx->log_payload_type = GNB_ES_PAYLOAD_TYPE_UDPLOG; if ( '\0' != log_udp_sockaddress4_string[0] ) { rc = gnb_log_udp_set_addr4_string(log_ctx, log_udp_sockaddress4_string); log_ctx->output_type |= GNB_LOG_OUTPUT_UDP; } return; } int main (int argc,char *argv[]){ char *ctl_block_file = NULL; char *pid_file = NULL; char *wan_address6_file = NULL; int upnp_opt = 0; char *upnp_multicase_if = NULL; char *upnp_gateway4 = NULL; int resolv_opt = 0; int broadcast_address_opt = 0; int discover_in_lan_opt = 0; int dump_address_opt = 0; int if_up_opt = 0; int if_down_opt = 0; int if_loop_opt = 0; int daemon = 0; int service_opt = 0; gnb_ctl_block_t *ctl_block; uint8_t log_udp_type = GNB_LOG_UDP_TYPE_TEXT; char log_udp_sockaddress4_string[16 + 1 + sizeof("65535")]; memset(log_udp_sockaddress4_string, 0, 16 + 1 + sizeof("65535")); int flag; struct option long_options[] = { { "ctl-block", required_argument, 0, 'b' }, { "upnp", no_argument, 0, OPT_UPNP }, { "upnp-multicase-if", required_argument, 0, OPT_UPNP_MULTICAST_IF }, { "upnp-gateway4", required_argument, 0, OPT_UPNP_GATEWAY4 }, { "resolv", no_argument, 0, OPT_RESOLV }, { "notify-address", no_argument, 0, OPT_NOTIFY_ADDRESS }, { "discover-in-lan", no_argument, 0, 'L' }, { "dump-address", no_argument, 0, OPT_DUMP_ADDRESS }, { "service", no_argument, 0, 's' }, { "daemon", no_argument, 0, 'd' }, { "pid-file", required_argument, 0, PID_FILE }, { "wan-address6-file", required_argument, 0, WAN_ADDRESS6_FILE }, { "if-up", no_argument, 0, OPT_IF_UP }, { "if-down", no_argument, 0, OPT_IF_DOWN }, { "if-loop", no_argument, 0, OPT_IF_LOOP }, { "log-udp6", optional_argument, &flag, LOG_UDP6 }, { "log-udp4", optional_argument, &flag, LOG_UDP4 }, { "log-udp-type", required_argument, 0, LOG_UDP_TYPE }, { "help", no_argument, 0, 'h' }, { 0, 0, 0, 0 } }; int opt; while (1) { int option_index = 0; opt = getopt_long (argc, argv, "b:46dsLh",long_options, &option_index); if ( opt == -1 ) { break; } switch (opt) { case 'b': ctl_block_file = optarg; break; case OPT_UPNP: upnp_opt = 1; break; case OPT_UPNP_MULTICAST_IF: upnp_multicase_if = optarg; upnp_opt = 1; break; case OPT_UPNP_GATEWAY4: upnp_gateway4 = optarg; upnp_opt = 1; break; case OPT_RESOLV: resolv_opt = 1; break; case 'L': discover_in_lan_opt = 1; break; case OPT_NOTIFY_ADDRESS: broadcast_address_opt = 1; break; case OPT_DUMP_ADDRESS: dump_address_opt = 1; break; case PID_FILE: pid_file = optarg; break; case WAN_ADDRESS6_FILE: wan_address6_file = optarg; break; case OPT_IF_UP: if_up_opt = 1; break; case OPT_IF_DOWN: if_down_opt = 1; break; case OPT_IF_LOOP: if_loop_opt = 1; break; case LOG_UDP_TYPE: if ( !strncmp(optarg, "binary", 16) ) { log_udp_type = GNB_LOG_UDP_TYPE_BINARY; } else { log_udp_type = GNB_LOG_UDP_TYPE_TEXT; } break; case 'd': daemon = 1; break; case 's': service_opt = 1; break; case 'h': show_useage(argc,argv); exit(0); default: break; } if ( 0 == opt ) { switch (flag) { case LOG_UDP4: if ( NULL != optarg ) { snprintf(log_udp_sockaddress4_string, 16 + 1 + sizeof("65535"), "%s", optarg); } else { snprintf(log_udp_sockaddress4_string, 16 + 1 + sizeof("65535"), "%s", "127.0.0.1:8666"); } break; default: break; } continue; } } if ( NULL == ctl_block_file ) { show_useage(argc,argv); exit(0); } #ifdef __UNIX_LIKE_OS__ if ( daemon ) { gnb_daemon(); } #endif if ( daemon ) { service_opt = 1; } gnb_log_ctx_t *log; log = gnb_log_ctx_create(); setup_log_ctx(log, log_udp_sockaddress4_string, log_udp_type); gnb_es_ctx *es_ctx = gnb_es_ctx_create(service_opt, ctl_block_file, log); if ( NULL == es_ctx ) { printf("es ctx init error [%s]......\n",ctl_block_file); return 1; } es_ctx->log = log; gnb_conf_t *conf = &es_ctx->ctl_block->conf_zone->conf_st; if ( 1 == conf->public_index_service ) { printf("gnb run as public index service map_file=%s\n", ctl_block_file); return 1; } if ( '\0' == conf->conf_dir[0] ) { if( 0 == conf->lite_mode ) { printf("gnb config dir is not set map_file=%s\n", ctl_block_file); return 1; } } es_ctx->pid_file = malloc(PATH_MAX+NAME_MAX); char resolved_path[PATH_MAX+NAME_MAX]; #ifdef __UNIX_LIKE_OS__ if ( NULL != pid_file ) { if ( 0 == conf->lite_mode ) { snprintf(es_ctx->pid_file, PATH_MAX+NAME_MAX,"%s", pid_file); } else { snprintf(conf->pid_file, PATH_MAX+NAME_MAX, "%s/gnb_es.%d.pid", conf->binary_dir, conf->udp4_ports[0]); } if ( NULL != gnb_realpath(es_ctx->pid_file,resolved_path) ) { strncpy(es_ctx->pid_file, resolved_path, PATH_MAX); } } else { snprintf(es_ctx->pid_file, PATH_MAX+NAME_MAX, "%s/gnb_es.pid", conf->conf_dir); } #endif if ( NULL != wan_address6_file ) { es_ctx->wan_address6_file = malloc(PATH_MAX+NAME_MAX); snprintf(es_ctx->wan_address6_file, PATH_MAX+NAME_MAX,"%s", wan_address6_file); if ( NULL != gnb_realpath(es_ctx->wan_address6_file,resolved_path) ) { strncpy(es_ctx->wan_address6_file, resolved_path, PATH_MAX); } } es_ctx->upnp_opt = upnp_opt; es_ctx->upnp_multicase_if = upnp_multicase_if; es_ctx->upnp_gateway4 = upnp_gateway4; es_ctx->resolv_opt = resolv_opt; es_ctx->broadcast_address_opt = broadcast_address_opt; es_ctx->discover_in_lan_opt = discover_in_lan_opt; es_ctx->dump_address_opt = dump_address_opt; es_ctx->if_up_opt = if_up_opt; es_ctx->if_down_opt = if_down_opt; es_ctx->if_loop_opt = if_loop_opt; es_ctx->daemon = daemon; es_ctx->service_opt = service_opt; #ifdef _WIN32 WSADATA wsaData; int err; err = WSAStartup(MAKEWORD(2, 2), &wsaData ); #endif #ifdef __UNIX_LIKE_OS__ if ( 1==es_ctx->service_opt || 1==es_ctx->daemon ) { save_pid(es_ctx->pid_file); } #endif gnb_es_ctx_init(es_ctx); gnb_start_environment_service(es_ctx); #ifdef _WIN32 WSACleanup(); #endif return 0; } opengnb-ver1.6.0.a/src/crypto/000077500000000000000000000000001500454252100162075ustar00rootroot00000000000000opengnb-ver1.6.0.a/src/crypto/arc4/000077500000000000000000000000001500454252100170405ustar00rootroot00000000000000opengnb-ver1.6.0.a/src/crypto/arc4/arc4.c000077500000000000000000000034631500454252100200460ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 "arc4.h" //参考来自这里的信息 //https://en.wikipedia.org/wiki/RC4 void arc4_init(struct arc4_sbox *sbox, unsigned char *key, unsigned int len) { register unsigned int x = 0; register unsigned int y = 0; sbox->x = 0; sbox->y = 0; for ( x=0; x<256; x++ ) { sbox->data[x] = x; } for ( x=0; x<256; x++ ) { y = ( y + sbox->data[x] + key[x%len]) % 256; sbox->data[x] ^= sbox->data[y]; sbox->data[y] ^= sbox->data[x]; sbox->data[x] ^= sbox->data[y]; } } void arc4_crypt(struct arc4_sbox *sbox, unsigned char*data, unsigned int len) { register unsigned int idx; register unsigned char k; register unsigned int x; register unsigned int y; x = sbox->x; y = sbox->y; for( idx=0; idxdata[x]) % 256; sbox->data[x] ^= sbox->data[y]; sbox->data[y] ^= sbox->data[x]; sbox->data[x] ^= sbox->data[y]; k = sbox->data[ ( sbox->data[x] + sbox->data[y] ) % 256]; data[idx] ^= k; } sbox->x = x; sbox->y = y; } opengnb-ver1.6.0.a/src/crypto/arc4/arc4.h000077500000000000000000000016751500454252100200560ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 . */ #ifndef ARC4_H #define ARC4_H struct arc4_sbox { unsigned int x; unsigned int y; unsigned char data[256]; }; void arc4_init(struct arc4_sbox *sbox, unsigned char *key, unsigned int len); void arc4_crypt(struct arc4_sbox *sbox, unsigned char*data, unsigned int len); #endif opengnb-ver1.6.0.a/src/crypto/random/000077500000000000000000000000001500454252100174675ustar00rootroot00000000000000opengnb-ver1.6.0.a/src/crypto/random/gnb_random.c000077500000000000000000000026561500454252100217550ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 #include #ifdef _WIN32 #include //unistd.h 定义了 _POSIX_THREAD_SAFE_FUNCTIONS 使得 localtime_r 有效 #include #endif #include #include "gnb_random.h" #include "gnb_binary.h" static uint64_t comput_random_seed(){ int ret; struct timeval cur_time; ret = gettimeofday(&cur_time,NULL); if (0!=ret) { return 0; } return cur_time.tv_usec; } unsigned char *gnb_random_data(unsigned char *buffer, size_t buffer_size){ uint64_t seed_u64; seed_u64 = comput_random_seed(); int seed = (int)seed_u64; srand(seed); int r; int i; for (i = 0; i < buffer_size; i++) { r = rand(); buffer[i] = r % 256; } return buffer; } opengnb-ver1.6.0.a/src/crypto/random/gnb_random.h000077500000000000000000000015111500454252100217470ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 . */ #ifndef GNB_RANDOM_H #define GNB_RANDOM_H #include #include unsigned char *gnb_random_data(unsigned char *buffer, size_t buffer_size); #endif opengnb-ver1.6.0.a/src/crypto/xor/000077500000000000000000000000001500454252100170175ustar00rootroot00000000000000opengnb-ver1.6.0.a/src/crypto/xor/xor.c000077500000000000000000000023671500454252100200060ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 . */ void xor_crypto(unsigned char *crypto_key, unsigned char *data, unsigned int len) { int i; int j = 0; for ( i=0; i= 64 ) { j = 0; } } } void xor_crypto_copy(unsigned char *crypto_key, unsigned char *dest, unsigned char *src, unsigned int len) { int i; int j = 0; for ( i=0; i= 64 ) { j = 0; } } } opengnb-ver1.6.0.a/src/crypto/xor/xor.h000077500000000000000000000016061500454252100200060ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 . */ #ifndef XOR_H #define XOR_H void xor_crypto(unsigned char *crypto_key, unsigned char *data, unsigned int len); void xor_crypto_copy(unsigned char *crypto_key, unsigned char *dest, unsigned char *src, unsigned int len); #endif opengnb-ver1.6.0.a/src/ctl/000077500000000000000000000000001500454252100154515ustar00rootroot00000000000000opengnb-ver1.6.0.a/src/ctl/gnb_ctl_dump.c000077500000000000000000000405111500454252100202560ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 #include #include #include #include "gnb_conf_type.h" #include "gnb_node_type.h" #include "gnb_address.h" #include "gnb_binary.h" #include "gnb_time.h" #include "gnb_udp.h" #include "gnb_ctl_block.h" #include "ed25519/sha512.h" #ifdef _WIN32 #include #include #include #endif void gnb_ctl_dump_status(gnb_ctl_block_t *ctl_block, gnb_uuid_t in_nodeid, uint8_t online_opt){ #define LINE_SIZE 1024 char line_string[LINE_SIZE]; char *p; int line_string_len; int wlen; gnb_conf_t *conf = NULL; gnb_address_t *gnb_address; char time_string[128]; char shared_secret_sha512[64]; char in_bytes_string[128]; char out_bytes_string[128]; conf = &ctl_block->conf_zone->conf_st; printf("conf->conf_dir[%s]\n",conf->conf_dir); gnb_address_list_t *available_address6_list; gnb_address_list_t *available_address4_list; gnb_address_list_t *static_address_list; gnb_address_list_t *dynamic_address_list; gnb_address_list_t *resolv_address_list; gnb_address_list_t *push_address_list; gnb_node_t *node; int node_num; node_num = ctl_block->node_zone->node_num; printf("node_num[%d]\n",node_num); printf("wan6_port[%d]\n", ntohs(ctl_block->core_zone->wan6_port) ); printf("wan4_port[%d]\n", ntohs(ctl_block->core_zone->wan4_port) ); int i,j; for ( i=0; inode_zone->node[i]; if ( 0 == in_nodeid ) { goto dump_all_node; } if ( 0 != in_nodeid && in_nodeid != node->uuid64 ) { continue; } dump_all_node: if ( 0 != online_opt && !((GNB_NODE_STATUS_IPV6_PONG | GNB_NODE_STATUS_IPV4_PONG) & node->udp_addr_status) ) { continue; } available_address6_list = (gnb_address_list_t *)&node->available_address6_list3_block; available_address4_list = (gnb_address_list_t *)&node->available_address4_list3_block; static_address_list = (gnb_address_list_t *)&node->static_address_block; dynamic_address_list = (gnb_address_list_t *)&node->dynamic_address_block; resolv_address_list = (gnb_address_list_t *)&node->resolv_address_block; push_address_list = (gnb_address_list_t *)&node->push_address_block; available_address6_list = (gnb_address_list_t *)&node->available_address6_list3_block; available_address4_list = (gnb_address_list_t *)&node->available_address4_list3_block; printf("\n====================\n"); printf("node %llu\n",node->uuid64); printf("addr4_ping_latency_usec %"PRIu64"\n",node->addr4_ping_latency_usec); printf("tun_ipv4 %s\n",GNB_ADDR4STR1(&node->tun_addr4)); printf("tun_ipv6 %s\n",GNB_ADDR6STR1(&node->tun_ipv6_addr)); if ( (node->in_bytes > 1024) && (node->in_bytes < 1024*1024) ) { snprintf(in_bytes_string, 128, "%.3fK bytes", ((float)node->in_bytes/1024)); } else if ( (node->in_bytes > 1024) && (node->in_bytes < 1024*1024*1024) ) { snprintf(in_bytes_string, 128, "%.3fM bytes", ((float)node->in_bytes/(1024*1024))); } else if ( (node->in_bytes >= 1024*1024*1024) ) { snprintf(in_bytes_string, 128, "%.3fG bytes", ((float)node->in_bytes/(1024*1024*1024))); } else { snprintf(in_bytes_string, 128, "%"PRIu64" bytes", node->in_bytes); } if ( (node->out_bytes > 1024) && (node->out_bytes < 1024*1024) ) { snprintf(out_bytes_string, 128, "%.3fK bytes", ((float)node->out_bytes/1024)); } else if ( (node->out_bytes > 1024) && (node->out_bytes < 1024*1024*1024) ) { snprintf(out_bytes_string, 128, "%.3fM bytes", ((float)node->out_bytes/(1024*1024))); } else if ( (node->out_bytes >= 1024*1024*1024) ) { snprintf(out_bytes_string, 128, "%.3fG bytes", ((float)node->out_bytes/(1024*1024*1024))); } else { snprintf(out_bytes_string, 128, "%"PRIu64" bytes", node->out_bytes); } printf("in %"PRIu64" (%s)\n", node->in_bytes, in_bytes_string); printf("out %"PRIu64" (%s)\n", node->out_bytes, out_bytes_string); printf("public_key %s\n",GNB_HEX1_BYTE64(node->public_key)); sha512((const unsigned char *)(node->shared_secret), 32, (unsigned char *)shared_secret_sha512); printf("shared_secret_sha512 %s\n",GNB_HEX1_BYTE128(shared_secret_sha512)); printf("crypto_key %s\n",GNB_HEX1_BYTE128(node->crypto_key)); printf("key512 %s\n",GNB_HEX1_BYTE64(node->key512)); if ( node->uuid64 != ctl_block->core_zone->local_uuid ) { if ( (node->udp_addr_status & GNB_NODE_STATUS_IPV6_PONG) ) { printf("ipv6 Direct Point to Point\n"); } else { printf("ipv6 InDirect\n"); } if ( (node->udp_addr_status & GNB_NODE_STATUS_IPV4_PONG) ) { printf("ipv4 Direct Point to Point\n"); } else { printf("ipv4 InDirect\n"); } } else { printf("ipv6 Local node\n"); printf("ipv4 Local node\n"); } gnb_timef("%Y-%m-%d %H:%M:%S", (time_t)node->ping_ts_sec, time_string, 128); printf("ping_ts_sec:%"PRIu64"(%s)\n", node->ping_ts_sec, time_string); printf("addr6_ping_latency_usec:%"PRIu64"\n", node->addr6_ping_latency_usec); printf("addr4_ping_latency_usec:%"PRIu64"\n", node->addr4_ping_latency_usec); printf("detect_count %u\n", node->detect_count); printf("wan_ipv4 %s\n", GNB_SOCKADDR4STR1(&node->udp_sockaddr4)); printf("wan_ipv6 %s\n", GNB_SOCKADDR6STR1(&node->udp_sockaddr6)); printf("available_address6:\n"); for ( j=0; jnum; j++ ) { gnb_address = &available_address6_list->array[j]; if ( 0==gnb_address->port ) { continue; } gnb_timef("%Y-%m-%d %H:%M:%S", (time_t)gnb_address->ts_sec, time_string, 128); printf("address %s ts_sec[%"PRIu64"](%s) latency_usec[%"PRIu64"]\n", GNB_IP_PORT_STR1(gnb_address), gnb_address->ts_sec, time_string, gnb_address->latency_usec); } printf("available_address4:\n"); for ( j=0; jnum; j++ ) { gnb_address = &available_address4_list->array[j]; if ( 0==gnb_address->port ) { continue; } gnb_timef("%Y-%m-%d %H:%M:%S", (time_t)gnb_address->ts_sec, time_string, 128); printf("address %s ts_sec[%"PRIu64"](%s) latency_usec[%"PRIu64"]\n", GNB_IP_PORT_STR1(gnb_address), gnb_address->ts_sec, time_string, gnb_address->latency_usec); } printf("static_address_list num[%lu]:\n",static_address_list->num); for ( j=0; jnum; j++ ) { gnb_address = &static_address_list->array[j]; if ( 0==gnb_address->port ) { continue; } gnb_timef("%Y-%m-%d %H:%M:%S", (time_t)gnb_address->ts_sec, time_string, 128); printf("address %s ts_sec[%"PRIu64"](%s) latency_usec[%"PRIu64"]\n", GNB_IP_PORT_STR1(gnb_address), gnb_address->ts_sec, time_string, gnb_address->latency_usec); } printf("dynamic_address_list num[%lu]:\n", dynamic_address_list->num); for ( j=0; jnum; j++ ) { gnb_address = &dynamic_address_list->array[j]; if ( 0==gnb_address->port ) { continue; } gnb_timef("%Y-%m-%d %H:%M:%S", (time_t)gnb_address->ts_sec, time_string, 128); printf("address idx=%u %s ts_sec[%"PRIu64"](%s) latency_usec[%"PRIu64"]\n", gnb_address->socket_idx, GNB_IP_PORT_STR1(gnb_address), gnb_address->ts_sec, time_string, gnb_address->latency_usec); } printf("resolv_address_list num[%lu]:\n",resolv_address_list->num); for ( j=0; jnum; j++ ) { gnb_address = &resolv_address_list->array[j]; if ( 0==gnb_address->port ) { continue; } gnb_timef("%Y-%m-%d %H:%M:%S", (time_t)gnb_address->ts_sec, time_string, 128); printf("address %s ts_sec[%"PRIu64"](%s) latency_usec[%"PRIu64"]\n", GNB_IP_PORT_STR1(gnb_address), gnb_address->ts_sec, time_string, gnb_address->latency_usec); } printf("push_address_list num[%lu]:\n",push_address_list->num); for ( j=0; jnum; j++ ) { gnb_address = &push_address_list->array[j]; if ( 0==gnb_address->port ) { continue; } gnb_timef("%Y-%m-%d %H:%M:%S", (time_t)gnb_address->ts_sec, time_string, 128); printf("address idx=%u %s ts_sec[%"PRIu64"](%s) latency_usec[%"PRIu64"]\n", gnb_address->socket_idx, GNB_IP_PORT_STR1(gnb_address), gnb_address->ts_sec, time_string, gnb_address->latency_usec); } p = line_string; wlen = 0; line_string_len = LINE_SIZE; for ( j=0; junified_forwarding_node_array[j].uuid64); line_string_len -= wlen; if ( line_string_len <= 16 ) { break; } p += wlen; } printf("unified node: %s\n", line_string); p = line_string; wlen = 0; line_string_len = LINE_SIZE; for ( j=0; junified_forwarding_recv_seq_array[j]); line_string_len -= wlen; if ( line_string_len <= 16 ) { break; } } printf("unified_forwarding_recv_seq_array: %s\n", line_string); } } void gnb_ctl_dump_address_list(gnb_ctl_block_t *ctl_block, gnb_uuid_t in_nodeid, uint8_t online_opt) { gnb_address_t *gnb_address; gnb_address_list_t *available_address6_list; gnb_address_list_t *available_address4_list; gnb_address_list_t *static_address_list; gnb_address_list_t *dynamic_address_list; gnb_address_list_t *resolv_address_list; gnb_address_list_t *push_address_list; gnb_node_t *node; int node_num; node_num = ctl_block->node_zone->node_num; int i,j; for ( i=0; inode_zone->node[i]; if ( 0 == in_nodeid ) { goto dump_all_node_address; } if ( 0 != in_nodeid && in_nodeid != node->uuid64 ) { continue; } dump_all_node_address: if ( node->uuid64 == ctl_block->core_zone->local_uuid ) { printf( "l|%llu|%s\n", node->uuid64, GNB_SOCKADDR6STR1(&node->udp_sockaddr6) ); printf( "l|%llu|%s\n", node->uuid64, GNB_SOCKADDR4STR1(&node->udp_sockaddr4) ); continue; } if ( 0 != online_opt && !((GNB_NODE_STATUS_IPV6_PONG | GNB_NODE_STATUS_IPV4_PONG) & node->udp_addr_status) ) { continue; } if ( GNB_NODE_STATUS_IPV6_PONG & node->udp_addr_status ) { printf( "w|%llu|%s\n", node->uuid64, GNB_SOCKADDR6STR1(&node->udp_sockaddr6) ); } if ( GNB_NODE_STATUS_IPV4_PONG & node->udp_addr_status ) { printf( "w|%llu|%s\n", node->uuid64, GNB_SOCKADDR4STR1(&node->udp_sockaddr4) ); } if ( 0 != online_opt ) { continue; } available_address6_list = (gnb_address_list_t *)&node->available_address6_list3_block; available_address4_list = (gnb_address_list_t *)&node->available_address4_list3_block; static_address_list = (gnb_address_list_t *)&node->static_address_block; dynamic_address_list = (gnb_address_list_t *)&node->dynamic_address_block; resolv_address_list = (gnb_address_list_t *)&node->resolv_address_block; push_address_list = (gnb_address_list_t *)&node->push_address_block; for ( j=0; jsize; j++ ) { gnb_address = &available_address6_list->array[j]; if ( 0==gnb_address->port ) { continue; } if ( AF_INET6 == gnb_address->type ) { printf( "a|%llu|%s|%d\n", node->uuid64, GNB_ADDR6STR1(&gnb_address->address.addr6), ntohs(gnb_address->port) ); } else if ( AF_INET == gnb_address->type ) { printf( "p|%llu|%s|%d\n", node->uuid64, GNB_ADDR4STR1(&gnb_address->address.addr4), ntohs(gnb_address->port) ); } else { continue; } } for ( j=0; jsize; j++ ) { gnb_address = &available_address4_list->array[j]; if ( 0==gnb_address->port ) { continue; } if ( AF_INET6 == gnb_address->type ) { printf( "a|%llu|%s|%d\n", node->uuid64, GNB_ADDR6STR1(&gnb_address->address.addr6), ntohs(gnb_address->port) ); } else if ( AF_INET == gnb_address->type ) { printf( "p|%llu|%s|%d\n", node->uuid64, GNB_ADDR4STR1(&gnb_address->address.addr4), ntohs(gnb_address->port) ); } else { continue; } } for ( j=0; jsize; j++ ) { gnb_address = &static_address_list->array[j]; if ( 0==gnb_address->port ) { continue; } if ( AF_INET6 == gnb_address->type ) { printf( "s|%llu|%s|%d\n", node->uuid64, GNB_ADDR6STR1(&gnb_address->address.addr6), ntohs(gnb_address->port) ); } else if ( AF_INET == gnb_address->type ) { printf( "s|%llu|%s|%d\n", node->uuid64, GNB_ADDR4STR1(&gnb_address->address.addr4), ntohs(gnb_address->port) ); } else { continue; } } for ( j=0; jsize; j++ ) { gnb_address = &dynamic_address_list->array[j]; if ( 0==gnb_address->port ) { continue; } if ( AF_INET6 == gnb_address->type ) { printf( "d|%llu|%s|%d\n", node->uuid64, GNB_ADDR6STR1(&gnb_address->address.addr6), ntohs(gnb_address->port) ); } else if ( AF_INET == gnb_address->type ) { printf( "d|%llu|%s|%d\n", node->uuid64, GNB_ADDR4STR1(&gnb_address->address.addr4), ntohs(gnb_address->port) ); } else { continue; } } for ( j=0; jsize; j++ ) { gnb_address = &resolv_address_list->array[j]; if ( 0==gnb_address->port ) { continue; } if ( AF_INET6 == gnb_address->type ) { printf( "r|%llu|%s|%d\n", node->uuid64, GNB_ADDR6STR1(&gnb_address->address.addr6), ntohs(gnb_address->port) ); } else if ( AF_INET == gnb_address->type ) { printf( "r|%llu|%s|%d\n", node->uuid64, GNB_ADDR4STR1(&gnb_address->address.addr4), ntohs(gnb_address->port) ); } else { continue; } } for ( j=0; jsize; j++ ) { gnb_address = &push_address_list->array[j]; if ( 0==gnb_address->port ) { continue; } if ( AF_INET6 == gnb_address->type ) { printf( "p|%llu|%s|%d\n", node->uuid64, GNB_ADDR6STR1(&gnb_address->address.addr6), ntohs(gnb_address->port) ); } else if ( AF_INET == gnb_address->type ) { printf( "p|%llu|%s|%d\n", node->uuid64, GNB_ADDR4STR1(&gnb_address->address.addr4), ntohs(gnb_address->port) ); } else { continue; } } } } opengnb-ver1.6.0.a/src/es/000077500000000000000000000000001500454252100152765ustar00rootroot00000000000000opengnb-ver1.6.0.a/src/es/gnb_discover_in_lan.c000077500000000000000000000401661500454252100214400ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 #include "gnb_es_type.h" #ifdef __UNIX_LIKE_OS__ #include /* for ifconf */ #include /* for sockaddr_in */ #include #include #include #include #include #include #include #endif #ifdef _WIN32 #include #include #include #include #include #endif #include "gnb_udp.h" #include "gnb_address.h" #include "gnb_node_type.h" #include "gnb_payload16.h" #include "gnb_discover_in_lan_frame_type.h" #include "gnb_pingpong_frame_type.h" #include "gnb_worker_type.h" #include "ed25519/ed25519.h" typedef struct _discover_in_lan_worker_ctx_t { gnb_es_ctx *es_ctx; pthread_t thread_worker; }discover_in_lan_worker_ctx_t; static void send_broadcast4(gnb_es_ctx *es_ctx, struct sockaddr_in *src_address_in, struct sockaddr_in *if_broadcast_address){ char payload_buffer[ PAYLOAD_DISCOVER_LAN_IN_FRAME_PAYLOAD_SIZE ]; gnb_payload16_t *payload; gnb_node_t *local_node; struct sockaddr_in broadcast_address_st; int broadcast_socket; int ret; int on; #if 0 local_node = (gnb_node_t *)GNB_HASH32_UINT64_GET_PTR(es_ctx->uuid_node_map, es_ctx->ctl_block->core_zone->local_uuid); if ( NULL == local_node ) { GNB_LOG1(es_ctx->log, GNB_LOG_ID_ES_DISCOVER_IN_LAN, "send broadcast4 error local node=%llu\n", es_ctx->ctl_block->core_zone->local_uuid); return; } #endif local_node = es_ctx->local_node; payload = (gnb_payload16_t *)payload_buffer; payload->type = GNB_PAYLOAD_TYPE_LAN_DISCOVER; payload->sub_type = 0; gnb_payload16_set_data_len( payload, sizeof(discover_lan_in_frame_t) ); discover_lan_in_frame_t *discover_lan_in_frame = (discover_lan_in_frame_t *)payload->data; memset(discover_lan_in_frame, 0, sizeof(discover_lan_in_frame_t)); memcpy(discover_lan_in_frame->data.src_key512, local_node->key512, 64); discover_lan_in_frame->data.src_uuid64 = gnb_htonll(local_node->uuid64); memcpy(discover_lan_in_frame->data.src_addr4, &src_address_in->sin_addr.s_addr, sizeof(struct in_addr)); discover_lan_in_frame->data.src_port4 = htons(es_ctx->ctl_block->conf_zone->conf_st.udp4_ports[0]); discover_lan_in_frame->data.src_ts_usec = gnb_htonll(es_ctx->now_time_usec); if ( NULL != if_broadcast_address ) { memcpy(&broadcast_address_st, if_broadcast_address, sizeof(struct sockaddr_in)); broadcast_address_st.sin_family = AF_INET; broadcast_address_st.sin_port = htons(DISCOVER_LAN_IN_BROADCAST_PORT); } else { memset(&broadcast_address_st, 0, sizeof(struct sockaddr_in)); broadcast_address_st.sin_family = AF_INET; broadcast_address_st.sin_port = htons(DISCOVER_LAN_IN_BROADCAST_PORT); broadcast_address_st.sin_addr.s_addr = INADDR_BROADCAST; } snprintf(discover_lan_in_frame->data.text, 256, "GNB LAN DISCOVER node=%llu address=%s,port=%d,broadcast_address=%s", local_node->uuid64, gnb_get_address4string(&src_address_in->sin_addr.s_addr, gnb_static_ip_port_string_buffer1, 0), es_ctx->ctl_block->conf_zone->conf_st.udp4_ports[0], gnb_get_address4string(&broadcast_address_st.sin_addr.s_addr, gnb_static_ip_port_string_buffer2, 0) ); broadcast_socket = socket(AF_INET, SOCK_DGRAM, 0); on = 1; ret = setsockopt(broadcast_socket, SOL_SOCKET, SO_BROADCAST, (const char *)&on, sizeof(on)); ret = bind(broadcast_socket, (struct sockaddr *)src_address_in, sizeof(struct sockaddr_in)); ret = sendto(broadcast_socket, (void *)payload, GNB_PAYLOAD16_FRAME_SIZE(payload), 0, (struct sockaddr*)&broadcast_address_st, sizeof(struct sockaddr_in)); GNB_LOG1(es_ctx->log, GNB_LOG_ID_ES_DISCOVER_IN_LAN, "send broadcast4 %s\n", discover_lan_in_frame->data.text); #ifdef __UNIX_LIKE_OS__ close(broadcast_socket); #endif #ifdef _WIN32 closesocket(broadcast_socket); #endif } static void handle_discover_lan_in_frame(gnb_es_ctx *es_ctx, gnb_payload16_t *in_payload, gnb_sockaddress_t *node_addr){ gnb_uuid_t in_src_uuid64; gnb_node_t *local_node; gnb_node_t *dst_node; uint16_t src_port4; discover_lan_in_frame_t *discover_lan_in_frame; node_ping_frame_t *node_ping_frame; gnb_payload16_t *payload; unsigned char payload_buffer[ NODE_PING_FRAME_PAYLOAD_SIZE ]; struct sockaddr_in udp_sockaddr4; if ( GNB_PAYLOAD_TYPE_LAN_DISCOVER != in_payload->type ) { GNB_LOG1(es_ctx->log, GNB_LOG_ID_ES_DISCOVER_IN_LAN, "handle_discover_lan_in_frame error in payload type=%d GNB_PAYLOAD_TYPE_LAN_DISCOVER=%d\n", in_payload->type, GNB_PAYLOAD_TYPE_LAN_DISCOVER); return; } local_node = (gnb_node_t *)GNB_HASH32_UINT64_GET_PTR(es_ctx->uuid_node_map, es_ctx->ctl_block->core_zone->local_uuid); if ( NULL == local_node ) { GNB_LOG1(es_ctx->log, GNB_LOG_ID_ES_DISCOVER_IN_LAN, "handle_discover_lan_in_frame error local_uuid=%llu\n", es_ctx->ctl_block->core_zone->local_uuid); return; } discover_lan_in_frame = (discover_lan_in_frame_t *)in_payload->data; in_src_uuid64 = gnb_ntohll(discover_lan_in_frame->data.src_uuid64); GNB_LOG1(es_ctx->log, GNB_LOG_ID_ES_DISCOVER_IN_LAN, "handle_discover_lan_in_frame src_node[%llu]\n", in_src_uuid64); if ( in_src_uuid64 == local_node->uuid64 ) { GNB_LOG1(es_ctx->log, GNB_LOG_ID_ES_DISCOVER_IN_LAN, "handle_discover_lan_in_frame error in_src_uuid64=%llu local_node->uuid64=%llu\n", in_src_uuid64, local_node->uuid64); return; } dst_node = (gnb_node_t *)GNB_HASH32_UINT64_GET_PTR(es_ctx->uuid_node_map, in_src_uuid64); if ( NULL == dst_node ) { GNB_LOG1(es_ctx->log, GNB_LOG_ID_ES_DISCOVER_IN_LAN, "handle_discover_lan_in_frame error dst node[%llu] not found!\n", in_src_uuid64); return; } payload = (gnb_payload16_t *)payload_buffer; payload->type = GNB_PAYLOAD_TYPE_NODE; payload->sub_type = PAYLOAD_SUB_TYPE_LAN_PING; gnb_payload16_set_data_len( payload, sizeof(node_ping_frame_t) ); node_ping_frame = (node_ping_frame_t *)payload->data; memset(node_ping_frame, 0, sizeof(node_ping_frame_t)); node_ping_frame->data.src_uuid64 = gnb_htonll(local_node->uuid64); node_ping_frame->data.dst_uuid64 = discover_lan_in_frame->data.src_uuid64; node_ping_frame->data.src_ts_usec = gnb_htonll(es_ctx->now_time_usec); src_port4 = htons(es_ctx->ctl_block->conf_zone->conf_st.udp4_ports[0]); memcpy(node_ping_frame->data.attachment, &src_port4, sizeof(uint16_t)); snprintf((char *)node_ping_frame->data.text, 32, "(LAN)%llu --PING-> %llu", local_node->uuid64, dst_node->uuid64); if ( 0 == es_ctx->ctl_block->conf_zone->conf_st.lite_mode ) { ed25519_sign(node_ping_frame->src_sign, (const unsigned char *)&node_ping_frame->data, sizeof(struct ping_frame_data), es_ctx->ctl_block->core_zone->ed25519_public_key, es_ctx->ctl_block->core_zone->ed25519_private_key); } memset(&udp_sockaddr4, 0, sizeof(struct sockaddr_in)); udp_sockaddr4.sin_family = AF_INET; memcpy(&udp_sockaddr4.sin_addr.s_addr, &discover_lan_in_frame->data.src_addr4, 4); udp_sockaddr4.sin_port = discover_lan_in_frame->data.src_port4; sendto(es_ctx->udp_socket4, (void *)payload, GNB_PAYLOAD16_FRAME_SIZE(payload), 0, (struct sockaddr *)&udp_sockaddr4, sizeof(struct sockaddr_in)); GNB_LOG1(es_ctx->log, GNB_LOG_ID_ES_DISCOVER_IN_LAN, "handle_discover_lan_in_frame send %s\n", node_ping_frame->data.text); return; } #ifdef _WIN32 #define WORKING_BUFFER_SIZE 15000 #define MAX_TRIES 3 #define MALLOC(x) HeapAlloc(GetProcessHeap(), 0, (x)) #define FREE(x) HeapFree(GetProcessHeap(), 0, (x)) void gnb_discover_in_lan_ipv4(gnb_es_ctx *es_ctx){ int i; ULONG family = AF_INET; DWORD dwRetVal = 0; ULONG outBufLen = 0; ULONG Iterations = 0; ULONG flags = GAA_FLAG_INCLUDE_PREFIX | GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_INCLUDE_GATEWAYS; outBufLen = WORKING_BUFFER_SIZE; PIP_ADAPTER_ADDRESSES pAddresses = NULL; PIP_ADAPTER_ADDRESSES pCurrAddresses = NULL; PIP_ADAPTER_DNS_SERVER_ADDRESS pDnServer = NULL; PIP_ADAPTER_UNICAST_ADDRESS pUnicast = NULL; struct sockaddr_in *sa_in; do { pAddresses = (IP_ADAPTER_ADDRESSES *) MALLOC(outBufLen); if (pAddresses == NULL) { GNB_LOG1(es_ctx->log, GNB_LOG_ID_ES_DISCOVER_IN_LAN, "Memory allocation failed for IP_ADAPTER_ADDRESSES struct\n"); exit(1); } dwRetVal = GetAdaptersAddresses(family, flags, NULL, pAddresses, &outBufLen); if (dwRetVal == ERROR_BUFFER_OVERFLOW) { FREE(pAddresses); pAddresses = NULL; } else { break; } Iterations++; } while ((dwRetVal == ERROR_BUFFER_OVERFLOW) && (Iterations < MAX_TRIES)); if (dwRetVal != NO_ERROR) { return; } pCurrAddresses = pAddresses; char friendlyname_string[256]; char description_string[256]; while (pCurrAddresses) { if ( IF_TYPE_ETHERNET_CSMACD != pCurrAddresses->IfType ) { goto next; } if ( IfOperStatusUp != pCurrAddresses->OperStatus ) { goto next; } WideCharToMultiByte(CP_ACP,WC_COMPOSITECHECK,pCurrAddresses->Description,-1,description_string,256,NULL,NULL); WideCharToMultiByte(CP_ACP,WC_COMPOSITECHECK,pCurrAddresses->FriendlyName,-1,friendlyname_string,256,NULL,NULL); if ( 0==strncmp( description_string, "TAP-Windows Adapter V9", sizeof("TAP-Windows Adapter V9")-1 ) ) { goto next; } GNB_LOG1(es_ctx->log, GNB_LOG_ID_ES_DISCOVER_IN_LAN, "IfIndex[%u] Adapter name: [%s] Adapter Description[%s]\n", pCurrAddresses->IfIndex, pCurrAddresses->AdapterName, description_string); pUnicast = pCurrAddresses->FirstUnicastAddress; if (NULL==pUnicast) { goto next; } for ( i=0; pUnicast!=NULL; i++ ) { if ( pUnicast->Address.lpSockaddr->sa_family == AF_INET ) { sa_in = (struct sockaddr_in *)pUnicast->Address.lpSockaddr; send_broadcast4(es_ctx, sa_in, NULL); } pUnicast = pUnicast->Next; } next: pCurrAddresses = pCurrAddresses->Next; } } #endif #ifdef __UNIX_LIKE_OS__ void gnb_discover_in_lan_ipv4(gnb_es_ctx *es_ctx){ struct ifaddrs *ifaddr; struct ifaddrs *ifa; struct sockaddr_in *in; struct sockaddr_in *broadcast_in; int ret; int n; ret = getifaddrs(&ifaddr); if ( -1 == ret ) { return; } for ( ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next ) { if ( ifa->ifa_addr == NULL ) { continue; } if ( AF_INET != ifa->ifa_addr->sa_family ) { continue; } if ( IFF_LOOPBACK & ifa->ifa_flags ) { continue; } if ( IFF_POINTOPOINT & ifa->ifa_flags ) { continue; } if ( !(IFF_UP & ifa->ifa_flags) ) { continue; } if ( !(IFF_RUNNING & ifa->ifa_flags) ) { continue; } if ( !(IFF_BROADCAST & ifa->ifa_flags) ) { continue; } in = (struct sockaddr_in *)ifa->ifa_addr; broadcast_in = (struct sockaddr_in *)ifa->ifa_broadaddr; GNB_LOG1(es_ctx->log, GNB_LOG_ID_ES_DISCOVER_IN_LAN, "ifa->ifa_name[%s] [%s] broadcast[%s]\n", ifa->ifa_name, gnb_get_address4string(&in->sin_addr.s_addr, gnb_static_ip_port_string_buffer1, 0), gnb_get_address4string(&broadcast_in->sin_addr.s_addr, gnb_static_ip_port_string_buffer2, 0) ); send_broadcast4(es_ctx, in, broadcast_in); } freeifaddrs(ifaddr); } #endif void gnb_discover_in_lan_service(gnb_es_ctx *es_ctx){ char buffer[ PAYLOAD_DISCOVER_LAN_IN_FRAME_PAYLOAD_SIZE ]; gnb_payload16_t *payload; int n_ready; int maxfd = 0; struct timeval timeout; fd_set readfds; fd_set allset; ssize_t n_recv; gnb_sockaddress_t node_addr_st; payload = (gnb_payload16_t *)buffer; FD_ZERO(&readfds); FD_ZERO(&allset); FD_SET(es_ctx->udp_discover_recv_socket4, &allset); maxfd = es_ctx->udp_discover_recv_socket4; readfds = allset; timeout.tv_sec = 0l; timeout.tv_usec = 10000l; n_ready = select( maxfd + 1, &readfds, NULL, NULL, &timeout ); if ( -1==n_ready ) { return; } if ( FD_ISSET( es_ctx->udp_discover_recv_socket4, &readfds ) ) { node_addr_st.socklen = sizeof(struct sockaddr_in); n_recv = recvfrom(es_ctx->udp_discover_recv_socket4, (void *)payload, PAYLOAD_DISCOVER_LAN_IN_FRAME_PAYLOAD_SIZE, 0, (struct sockaddr *)&node_addr_st.addr.in, &node_addr_st.socklen); if ( -1 == n_recv ) { return; } if ( PAYLOAD_DISCOVER_LAN_IN_FRAME_PAYLOAD_SIZE != n_recv ) { return; } node_addr_st.addr_type = AF_INET; handle_discover_lan_in_frame(es_ctx, payload, &node_addr_st); } } static void* thread_worker_func( void *data ) { gnb_worker_t *discover_in_lan_worker = (gnb_worker_t *)data; discover_in_lan_worker_ctx_t *discover_in_lan_worker_ctx = (discover_in_lan_worker_ctx_t *)discover_in_lan_worker->ctx; gnb_es_ctx *es_ctx = discover_in_lan_worker_ctx->es_ctx; discover_in_lan_worker->thread_worker_flag = 1; discover_in_lan_worker->thread_worker_run_flag = 1; do{ gnb_discover_in_lan_service(es_ctx); }while(discover_in_lan_worker->thread_worker_flag); discover_in_lan_worker->thread_worker_run_flag = 0; return NULL; } static void init(gnb_worker_t *gnb_worker, void *ctx){ gnb_es_ctx *es_ctx; discover_in_lan_worker_ctx_t *discover_in_lan_worker_ctx; int on; int ret; struct sockaddr_in svr_addr; discover_in_lan_worker_ctx = (discover_in_lan_worker_ctx_t *)malloc(sizeof(discover_in_lan_worker_ctx_t)); memset(discover_in_lan_worker_ctx, 0, sizeof(discover_in_lan_worker_ctx_t)); es_ctx = (gnb_es_ctx *)ctx; discover_in_lan_worker_ctx->es_ctx = es_ctx; es_ctx->udp_discover_recv_socket4 = socket(AF_INET, SOCK_DGRAM, 0); memset(&svr_addr, 0, sizeof(struct sockaddr_in)); svr_addr.sin_family = AF_INET; svr_addr.sin_addr.s_addr = htonl(INADDR_ANY); svr_addr.sin_port = htons(DISCOVER_LAN_IN_BROADCAST_PORT); ret = bind(es_ctx->udp_discover_recv_socket4, (struct sockaddr *)&svr_addr, sizeof(struct sockaddr_in)); on = 1; ret = setsockopt(es_ctx->udp_discover_recv_socket4, SOL_SOCKET, SO_BROADCAST, (const char *)&on, sizeof(on)); gnb_worker->ctx = discover_in_lan_worker_ctx; } static void release(gnb_worker_t *gnb_worker){ } static int start(gnb_worker_t *gnb_worker){ discover_in_lan_worker_ctx_t *discover_in_lan_worker_ctx = (discover_in_lan_worker_ctx_t *)gnb_worker->ctx; pthread_create(&discover_in_lan_worker_ctx->thread_worker, NULL, thread_worker_func, gnb_worker); pthread_detach(discover_in_lan_worker_ctx->thread_worker); return 0; } static int stop(gnb_worker_t *gnb_worker){ return 0; } static int notify(gnb_worker_t *gnb_worker){ return 0; } gnb_worker_t gnb_discover_in_lan_worker_mod = { .name = "gnb_discover_in_lan_worker", .init = init, .release = release, .start = start, .stop = stop, .notify = notify, .ctx = NULL }; opengnb-ver1.6.0.a/src/es/gnb_environment_service.c000077500000000000000000000171571500454252100223720ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 #include #include #include #include "gnb_es_type.h" #include "gnb_udp.h" #include "gnb_time.h" #include "gnb_mmap.h" #include "gnb_address.h" #ifdef __UNIX_LIKE_OS__ #include #include #include #endif #ifdef _WIN32 #undef _WIN32_WINNT #define _WIN32_WINNT 0x0600 #include #include #endif extern gnb_worker_t gnb_discover_in_lan_worker_mod; void gnb_set_env(const char *name, const char *value); void gnb_es_dump_address_list(gnb_es_ctx *es_ctx); void gnb_broadcast_address(gnb_es_ctx *es_ctx); void gnb_es_upnp(gnb_es_ctx *es_ctx, gnb_conf_t *conf, gnb_log_ctx_t *log); void gnb_resolv_address(gnb_es_ctx *es_ctx); void gnb_load_wan_ipv6_address(gnb_es_ctx *es_ctx); void gnb_discover_in_lan_ipv4(gnb_es_ctx *es_ctx); void gnb_es_if_up(gnb_es_ctx *es_ctx); void gnb_es_if_down(gnb_es_ctx *es_ctx); void gnb_es_if_loop(gnb_es_ctx *es_ctx); static void sync_es_time(gnb_es_ctx *es_ctx){ gettimeofday(&es_ctx->now_timeval, NULL); es_ctx->now_time_sec = (uint64_t)es_ctx->now_timeval.tv_sec; es_ctx->now_time_usec = (uint64_t)es_ctx->now_timeval.tv_sec *1000000 + es_ctx->now_timeval.tv_usec; } gnb_es_ctx* gnb_es_ctx_create(int is_service, char *ctl_block_file, gnb_log_ctx_t *log){ ssize_t ctl_file_size = 0; gnb_mmap_block_t *mmap_block; void *block; char *memory; gnb_ctl_block_t *ctl_block = NULL; if ( 0 == is_service ) { ctl_block = gnb_get_ctl_block(ctl_block_file, 1); if ( NULL != ctl_block ) { goto gnb_map_init_success; } else { return NULL; } } int try_count = 0; do{ ctl_block = gnb_get_ctl_block(ctl_block_file, 1); if ( NULL == ctl_block ) { goto wait_gnb_init; } memory = (char *)ctl_block->entry_table256; memory[CTL_BLOCK_ES_MAGIC_IDX] = 'E'; break; wait_gnb_init: GNB_LOG1(log, GNB_LOG_ID_ES_CORE, "Wait For GNB init...\n"); GNB_SLEEP_MILLISECOND(300); try_count++; if ( try_count > 100 ) { GNB_LOG1(log, GNB_LOG_ID_ES_CORE, "GNB init timeout\n"); } }while(1); gnb_map_init_success: GNB_LOG1(log, GNB_LOG_ID_ES_CORE, "open ctl block success [%s]\n", ctl_block->magic_number->data); gnb_node_t *node; int node_num; gnb_heap_t *heap = gnb_heap_create(8192); gnb_es_ctx *es_ctx = (gnb_es_ctx *)gnb_heap_alloc(heap,sizeof(gnb_es_ctx)); memset(es_ctx, 0, sizeof(gnb_es_ctx)); es_ctx->heap = heap; es_ctx->ctl_block = ctl_block; //对 node 进行索引 es_ctx->uuid_node_map = gnb_hash32_create(es_ctx->heap,1024,1024); node_num = es_ctx->ctl_block->node_zone->node_num; if ( 0 == node_num ) { goto finish; } int i; for ( i=0; ictl_block->node_zone->node[i]; GNB_HASH32_UINT64_SET(es_ctx->uuid_node_map, node->uuid64, node); } es_ctx->local_node = (gnb_node_t *)GNB_HASH32_UINT64_GET_PTR(es_ctx->uuid_node_map, es_ctx->ctl_block->core_zone->local_uuid); if ( NULL == es_ctx->local_node ) { GNB_LOG1(log, GNB_LOG_ID_ES_CORE, "gnb_es_ctx_create local node=%llu\n", es_ctx->ctl_block->core_zone->local_uuid); return NULL; } finish: return es_ctx; } void gnb_es_ctx_init(gnb_es_ctx *es_ctx){ gnb_worker_t *gnb_worker_mod; es_ctx->udp_socket4 = socket(AF_INET, SOCK_DGRAM, 0); gnb_bind_udp_socket_ipv4(es_ctx->udp_socket4, "0.0.0.0", 0); es_ctx->udp_socket6 = socket(AF_INET6, SOCK_DGRAM, 0); gnb_bind_udp_socket_ipv6(es_ctx->udp_socket6, "::", 0); if ( es_ctx->discover_in_lan_opt && es_ctx->service_opt ) { gnb_worker_mod = &gnb_discover_in_lan_worker_mod; es_ctx->discover_in_lan_worker = (gnb_worker_t *)malloc(sizeof(gnb_worker_t)); *es_ctx->discover_in_lan_worker = *gnb_worker_mod; es_ctx->discover_in_lan_worker->thread_worker_flag = 0; es_ctx->discover_in_lan_worker->thread_worker_run_flag = 0; es_ctx->discover_in_lan_worker->init(es_ctx->discover_in_lan_worker, es_ctx); } } static void gnb_es_setup_env(gnb_es_ctx *es_ctx){ char env_value_string[64]; gnb_set_env("GNB_IF_NAME", (const char *)es_ctx->ctl_block->core_zone->ifname); snprintf(env_value_string, 64, "%d", es_ctx->ctl_block->conf_zone->conf_st.mtu); gnb_set_env("GNB_MTU", env_value_string); gnb_set_env("GNB_TUN_IPV4", GNB_ADDR4STR1(&es_ctx->local_node->tun_addr4)); gnb_set_env("GNB_TUN_IPV6", GNB_ADDR6STR1(&es_ctx->local_node->tun_ipv6_addr)); } #define GNB_RESOLV_INTERVAL_SEC 900 #define GNB_UPNP_INTERVAL_SEC 145 #define GNB_DUMP_ADDRESS_INTERVAL_SEC 15 #define GNB_BROADCAST_INTERVAL_SEC 300 #define GNB_DISCOVER_IN_LAN_INTERVAL_SEC 60 void gnb_start_environment_service(gnb_es_ctx *es_ctx){ uint64_t last_resolv_address_sec = 0; uint64_t last_upnp_time_sec = 0; uint64_t last_dump_address_sec = 0; uint64_t last_broadcast_address_sec = 0; uint64_t last_discover_in_lan_sec = 0; gnb_es_setup_env(es_ctx); if ( es_ctx->if_up_opt ) { gnb_es_if_up(es_ctx); return; } if ( es_ctx->if_down_opt ) { gnb_es_if_down(es_ctx); return; } if ( es_ctx->service_opt && es_ctx->discover_in_lan_opt ) { es_ctx->discover_in_lan_worker->start(es_ctx->discover_in_lan_worker); } do{ sync_es_time(es_ctx); if ( es_ctx->resolv_opt && (es_ctx->now_time_sec - last_resolv_address_sec ) > GNB_RESOLV_INTERVAL_SEC ) { gnb_resolv_address(es_ctx); gnb_load_wan_ipv6_address(es_ctx); last_resolv_address_sec = es_ctx->now_time_sec; } if ( es_ctx->if_loop_opt ) { gnb_es_if_loop(es_ctx); } if ( es_ctx->upnp_opt && (es_ctx->now_time_sec - last_upnp_time_sec ) > GNB_UPNP_INTERVAL_SEC ) { gnb_es_upnp(es_ctx, &es_ctx->ctl_block->conf_zone->conf_st, es_ctx->log); last_upnp_time_sec = es_ctx->now_time_sec; } if ( es_ctx->dump_address_opt && (es_ctx->now_time_sec - last_dump_address_sec ) > GNB_DUMP_ADDRESS_INTERVAL_SEC ) { gnb_es_dump_address_list(es_ctx); last_dump_address_sec = es_ctx->now_time_sec; } if ( es_ctx->broadcast_address_opt && (es_ctx->now_time_sec - last_broadcast_address_sec ) > GNB_BROADCAST_INTERVAL_SEC ) { gnb_broadcast_address(es_ctx); last_broadcast_address_sec = es_ctx->now_time_sec; } if ( es_ctx->discover_in_lan_opt && (es_ctx->now_time_sec - last_discover_in_lan_sec ) > GNB_DISCOVER_IN_LAN_INTERVAL_SEC ) { gnb_discover_in_lan_ipv4(es_ctx); last_discover_in_lan_sec = es_ctx->now_time_sec; } GNB_SLEEP_MILLISECOND(100); }while(es_ctx->service_opt); } void gnb_stop_environment_service(gnb_es_ctx *es_ctx){ } opengnb-ver1.6.0.a/src/es/gnb_es_broadcast_address.c000077500000000000000000000114461500454252100224370ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 #include #include #include #include "gnb_es_type.h" #ifdef __UNIX_LIKE_OS__ #include #include #endif #ifdef _WIN32 #include #include #include #endif #include "gnb_conf_type.h" #include "gnb_node_type.h" #include "gnb_ctl_block.h" #include "gnb_payload16.h" #include "gnb_address.h" #include "gnb_time.h" #include "gnb_binary.h" #include "gnb_udp.h" #include "gnb_index_frame_type.h" static void send_address_to_node(gnb_es_ctx *es_ctx, gnb_node_t *src_node, gnb_node_t *dst_node){ unsigned char payload_buffer[ PUSH_ADDR_FRAME_PAYLOAD_SIZE ]; gnb_payload16_t *payload; gnb_ctl_block_t *ctl_block; gnb_log_ctx_t *log; ctl_block = es_ctx->ctl_block; log = es_ctx->log; payload = (gnb_payload16_t *)payload_buffer; memset(payload_buffer, 0, PUSH_ADDR_FRAME_PAYLOAD_SIZE); payload->type = GNB_PAYLOAD_TYPE_INDEX; payload->sub_type = PAYLOAD_SUB_TYPE_PUSH_ADDR; gnb_payload16_set_data_len( payload, sizeof(push_addr_frame_t) ); push_addr_frame_t *push_addr_frame = (push_addr_frame_t *)payload->data; push_addr_frame->data.node_uuid64 = gnb_htonll(src_node->uuid64); memcpy(push_addr_frame->data.node_key, src_node->key512, 64); push_addr_frame->data.arg0 = 'N'; memcpy(&push_addr_frame->data.addr6_a, &src_node->udp_sockaddr6.sin6_addr, 16); push_addr_frame->data.port6_a = src_node->udp_sockaddr6.sin6_port; memcpy(&push_addr_frame->data.addr4_a, &src_node->udp_sockaddr4.sin_addr.s_addr, 4); push_addr_frame->data.port4_a = src_node->udp_sockaddr4.sin_port; snprintf(push_addr_frame->data.text,32,"%llu>%llu>%llu", ctl_block->core_zone->local_uuid, src_node->uuid64, dst_node->uuid64); struct sockaddr_in udp_sockaddr4; memset(&udp_sockaddr4, 0, sizeof(struct sockaddr_in)); memcpy(&udp_sockaddr4.sin_addr.s_addr,&dst_node->tun_addr4.s_addr,4); udp_sockaddr4.sin_port = dst_node->tun_sin_port4; udp_sockaddr4.sin_family = AF_INET; sendto(es_ctx->udp_socket4, (void *)payload, GNB_PAYLOAD16_FRAME_SIZE(payload), 0, (struct sockaddr *)&udp_sockaddr4, sizeof(struct sockaddr_in)); GNB_LOG1(log, GNB_LOG_ID_ES_BROADCAST, "send_address_to_node %s\n", GNB_SOCKADDR4STR1(&udp_sockaddr4)); } static void broadcast_address_to_node(gnb_es_ctx *es_ctx, gnb_node_t *src_node){ gnb_ctl_block_t *ctl_block; gnb_node_t *dst_node; gnb_log_ctx_t *log; int node_num; int i; ctl_block = es_ctx->ctl_block; log = es_ctx->log; node_num = ctl_block->node_zone->node_num; for ( i=0; inode_zone->node[i]; if ( dst_node->uuid64 == src_node->uuid64 ) { continue; } if ( src_node->uuid64 == ctl_block->core_zone->local_uuid ) { continue; } if ( dst_node->uuid64 == ctl_block->core_zone->local_uuid ) { continue; } if ( !( (GNB_NODE_STATUS_IPV6_PONG|GNB_NODE_STATUS_IPV4_PONG) & dst_node->udp_addr_status ) ) { continue; } if ( 0 == dst_node->tun_sin_port4 ) { continue; } if ( (dst_node->type & GNB_NODE_TYPE_IDX) || (dst_node->type & GNB_NODE_TYPE_FWD) ) { continue; } GNB_LOG1(log, GNB_LOG_ID_ES_BROADCAST, "broadcast_address_to_node [%llu] ==> [%llu]\n", src_node->uuid64, dst_node->uuid64); send_address_to_node(es_ctx, src_node, dst_node); } } void gnb_broadcast_address(gnb_es_ctx *es_ctx){ gnb_ctl_block_t *ctl_block; gnb_node_t *node; int node_num; int i; ctl_block = es_ctx->ctl_block; node_num = ctl_block->node_zone->node_num; if ( 0 == node_num ) { return; } for ( i=0; inode_zone->node[i]; if ( !( (GNB_NODE_STATUS_IPV6_PONG|GNB_NODE_STATUS_IPV4_PONG) & node->udp_addr_status ) ) { continue; } if ( (node->type & GNB_NODE_TYPE_IDX) || (node->type & GNB_NODE_TYPE_FWD) ) { continue; } broadcast_address_to_node(es_ctx, node); } } opengnb-ver1.6.0.a/src/es/gnb_es_dump.c000077500000000000000000000115441500454252100177340ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 #include #include #include "gnb_conf_type.h" #include "gnb_node_type.h" #include "gnb_ctl_block.h" #include "gnb_es_type.h" #include "gnb_address.h" #include "gnb_binary.h" void gnb_es_dump_address_list(gnb_es_ctx *es_ctx){ gnb_address_t *gnb_address; gnb_address_list_t *static_address_list; gnb_address_list_t *dynamic_address_list; gnb_address_list_t *resolv_address_list; gnb_address_list_t *push_address_list; gnb_node_t *node; int node_num; gnb_conf_t *conf; conf = &es_ctx->ctl_block->conf_zone->conf_st; if ( '\0' == conf->node_cache_file[0] ) { return; } node_num = es_ctx->ctl_block->node_zone->node_num; if ( 0==node_num ) { return; } FILE *file; file = fopen(conf->node_cache_file,"wb"); if ( NULL == file ) { return; } int i,j; for( i=0; ictl_block->node_zone->node[i]; static_address_list = (gnb_address_list_t *)&node->static_address_block; dynamic_address_list = (gnb_address_list_t *)&node->dynamic_address_block; resolv_address_list = (gnb_address_list_t *)&node->resolv_address_block; push_address_list = (gnb_address_list_t *)&node->push_address_block; for ( j=0; jsize; j++ ) { gnb_address = &static_address_list->array[j]; if (0==gnb_address->port) { continue; } if ( AF_INET6 == gnb_address->type ) { fprintf( file, "s|%llu|%s|%d|%s\n", node->uuid64, GNB_ADDR6STR_PLAINTEXT1(&gnb_address->address.addr6), ntohs(gnb_address->port), GNB_HEX1_BYTE128(node->key512) ); } else if ( AF_INET == gnb_address->type ) { fprintf( file, "s|%llu|%s|%d|%s\n", node->uuid64, GNB_ADDR4STR_PLAINTEXT1(&gnb_address->address.addr4), ntohs(gnb_address->port), GNB_HEX1_BYTE128(node->key512) ); } else { continue; } } for ( j=0; jsize; j++ ) { gnb_address = &dynamic_address_list->array[j]; if (0==gnb_address->port) { continue; } if ( AF_INET6 == gnb_address->type ) { fprintf( file, "d|%llu|%s|%d|%s\n", node->uuid64, GNB_ADDR6STR_PLAINTEXT1(&gnb_address->address.addr6), ntohs(gnb_address->port), GNB_HEX1_BYTE128(node->key512) ); } else if ( AF_INET == gnb_address->type ) { fprintf( file, "d|%llu|%s|%d|%s\n", node->uuid64, GNB_ADDR4STR_PLAINTEXT1(&gnb_address->address.addr4), ntohs(gnb_address->port), GNB_HEX1_BYTE128(node->key512) ); } else { continue; } } for ( j=0; jsize; j++ ) { gnb_address = &resolv_address_list->array[j]; if (0==gnb_address->port) { continue; } if ( AF_INET6 == gnb_address->type ) { fprintf( file, "r|%llu|%s|%d|%s\n", node->uuid64, GNB_ADDR6STR_PLAINTEXT1(&gnb_address->address.addr6), ntohs(gnb_address->port), GNB_HEX1_BYTE128(node->key512) ); } else if ( AF_INET == gnb_address->type ) { fprintf( file, "r|%llu|%s|%d|%s\n", node->uuid64, GNB_ADDR4STR_PLAINTEXT1(&gnb_address->address.addr4), ntohs(gnb_address->port), GNB_HEX1_BYTE128(node->key512) ); } else { continue; } } for ( j=0; jsize; j++ ) { gnb_address = &push_address_list->array[j]; if (0==gnb_address->port) { continue; } if ( AF_INET6 == gnb_address->type ) { fprintf( file, "p|%llu|%s|%d|%s\n", node->uuid64, GNB_ADDR6STR_PLAINTEXT1(&gnb_address->address.addr6), ntohs(gnb_address->port), GNB_HEX1_BYTE128(node->key512) ); } else if ( AF_INET == gnb_address->type ) { fprintf( file, "p|%llu|%s|%d|%s\n", node->uuid64, GNB_ADDR4STR_PLAINTEXT1(&gnb_address->address.addr4), ntohs(gnb_address->port), GNB_HEX1_BYTE128(node->key512) ); } else { continue; } } } fclose(file); } opengnb-ver1.6.0.a/src/es/gnb_es_platform.c000077500000000000000000000032351500454252100206110ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 #include #include #ifdef _WIN32 #include #include #endif #include "gnb_es_type.h" #ifdef _WIN32 static void windows_if_up(gnb_es_ctx *es_ctx){ gnb_conf_t *conf; gnb_ctl_core_zone_t *core_zone; conf = &es_ctx->ctl_block->conf_zone->conf_st; core_zone = es_ctx->ctl_block->core_zone; char cmd[1024]; char *devicename; char *if_device_string; devicename = core_zone->ifname; if_device_string = core_zone->if_device_string; //修改tun设备的MTU snprintf(cmd,1024,"netsh interface ipv4 set subinterface interface=\"%s\" mtu=%d store=active >NUL 2>&1", devicename, conf->mtu); system(cmd); } static void windows_if_down(gnb_es_ctx *es_ctx){ } #endif void gnb_es_if_up(gnb_es_ctx *es_ctx){ #ifdef _WIN32 windows_if_up(es_ctx); #endif } void gnb_es_if_down(gnb_es_ctx *es_ctx){ #ifdef _WIN32 windows_if_down(es_ctx); #endif } void gnb_es_if_loop(gnb_es_ctx *es_ctx){ } opengnb-ver1.6.0.a/src/es/gnb_es_resolv.c000077500000000000000000000140211500454252100202720ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 . */ #if defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) || defined(__OpenBSD__) #define __UNIX_LIKE_OS__ 1 #endif #include #include #include #include #include #ifdef __UNIX_LIKE_OS__ #include #include #endif #if defined(_WIN32) #undef _WIN32_WINNT #define _WIN32_WINNT 0x0600 #include #include #endif #include "gnb_node_type.h" #include "gnb_address.h" #include "gnb_es_type.h" int gnb_test_field_separator(char *config_string); static char * check_domain_name(char *host_string){ if ( NULL != strchr(host_string, ':') ){ return NULL; } int i; for ( i=0; i= 'a' && host_string[i] <= 'z' ) { return host_string; } } return NULL; } static void gnb_do_resolv_node_address(gnb_node_t *node, char *host_string, uint16_t port, gnb_log_ctx_t *log){ int ret; struct addrinfo hints; memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_CANONNAME; struct addrinfo *result; struct addrinfo *cur; ret = getaddrinfo(host_string, NULL, &hints, &result); if ( -1 == ret ) { return; } gnb_address_list_t *resolv_address_list; gnb_address_t address_st; resolv_address_list = (gnb_address_list_t *)&node->resolv_address_block; for ( cur=result; NULL!=cur; cur=cur->ai_next ) { memset(&address_st, 0, sizeof(gnb_address_t)); address_st.port = htons(port); switch(cur->ai_addr->sa_family) { case AF_INET6: address_st.type = AF_INET6; memcpy(&address_st.m_address6, &(((struct sockaddr_in6 *)(cur->ai_addr))->sin6_addr), 16); gnb_address_list_update(resolv_address_list, &address_st); break; case AF_INET: address_st.type = AF_INET; memcpy(&address_st.m_address4, &(((struct sockaddr_in *)(cur->ai_addr))->sin_addr), 4); gnb_address_list_update(resolv_address_list, &address_st); break; default: break; } } freeaddrinfo(result); gnb_address_t *gnb_address; int j; for( j=0; jsize; j++ ) { gnb_address = &resolv_address_list->array[j]; if (0==gnb_address->port) { continue; } GNB_LOG1(log, GNB_LOG_ID_ES_RESOLV, "resolv [%s]>[%s]\n", host_string, GNB_IP_PORT_STR1(gnb_address)); } } void gnb_resolv_address(gnb_es_ctx *es_ctx){ gnb_log_ctx_t *log = es_ctx->log; char *conf_dir = es_ctx->ctl_block->conf_zone->conf_st.conf_dir; char address_file[PATH_MAX+NAME_MAX]; snprintf(address_file, PATH_MAX+NAME_MAX, "%s/%s", conf_dir, "address.conf"); FILE *file; file = fopen(address_file,"r"); if ( NULL==file ) { return; } char line_buffer[1024+1]; char attrib_string[16+1]; gnb_uuid_t uuid64; char host_string[256+1]; uint16_t port = 0; gnb_node_t *node; int num; int ret; do{ num = fscanf(file,"%1024s\n",line_buffer); if ( EOF == num ) { break; } if ('#' == line_buffer[0]) { continue; } ret = gnb_test_field_separator(line_buffer); if ( GNB_CONF_FIELD_SEPARATOR_TYPE_SLASH == ret ) { num = sscanf(line_buffer,"%16[^/]/%llu/%256[^/]/%hu\n", attrib_string, &uuid64, host_string, &port); } else if ( GNB_CONF_FIELD_SEPARATOR_TYPE_VERTICAL == ret ) { num = sscanf(line_buffer,"%16[^|]|%llu|%256[^|]|%hu\n", attrib_string, &uuid64, host_string, &port); } else { num = 0; } if ( 4 != num ) { continue; } if ( 0 == port ) { continue; } if ( NULL == check_domain_name(host_string) ) { continue; } node = (gnb_node_t *)GNB_HASH32_UINT64_GET_PTR(es_ctx->uuid_node_map, uuid64); if ( NULL == node ) { continue; } gnb_do_resolv_node_address(node, host_string, port,log); }while(1); fclose(file); } /* dig -6 TXT +short o-o.myaddr.l.google.com @ns1.google.com | awk -F'"' '{ print $2}' */ void gnb_load_wan_ipv6_address(gnb_es_ctx *es_ctx){ gnb_log_ctx_t *log = es_ctx->log; if ( NULL == es_ctx->wan_address6_file ) { return; } FILE *file; file = fopen(es_ctx->wan_address6_file,"r"); if ( NULL == file ) { return; } gnb_conf_t *conf = &es_ctx->ctl_block->conf_zone->conf_st; char host_string[46+1]; int num; num = fscanf(file,"%46s\n",host_string); int s; s = inet_pton(AF_INET6, host_string, (struct in_addr *)&es_ctx->ctl_block->core_zone->wan6_addr); if (s <= 0) { memset(&es_ctx->ctl_block->core_zone->wan6_addr,0,16); es_ctx->ctl_block->core_zone->wan6_port = 0; } else { es_ctx->ctl_block->core_zone->wan6_port = htons(conf->udp6_ports[0]); GNB_LOG1(log, GNB_LOG_ID_ES_RESOLV, "load wan address6[%s:%d]\n", host_string, conf->udp6_ports[0]); } } opengnb-ver1.6.0.a/src/es/gnb_es_type.h000077500000000000000000000037641500454252100177620ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 . */ #ifndef gnb_es_type_h #define gnb_es_type_h #if defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) || defined(__OpenBSD__) #define __UNIX_LIKE_OS__ 1 #endif #include #include #include #include "gnb_alloc.h" #include "gnb_conf_type.h" #include "gnb_ctl_block.h" #include "gnb_hash32.h" #include "gnb_node_type.h" #include "gnb_worker_type.h" #include "gnb_log.h" typedef struct _gnb_es_ctx{ gnb_heap_t *heap; struct timeval now_timeval; uint64_t now_time_sec; uint64_t now_time_usec; int udp_socket4; int udp_socket6; int udp_discover_recv_socket4; gnb_ctl_block_t *ctl_block; gnb_hash32_map_t *uuid_node_map; gnb_node_t *local_node; gnb_worker_t *discover_in_lan_worker; char *pid_file; char *wan_address6_file; int service_opt; int upnp_opt; char *upnp_multicase_if; char *upnp_gateway4; int resolv_opt; int broadcast_address_opt; int discover_in_lan_opt; int dump_address_opt; int if_up_opt; int if_down_opt; int if_loop_opt; gnb_log_ctx_t *log; int daemon; }gnb_es_ctx; #define GNB_LOG_ID_ES_CORE 0 #define GNB_LOG_ID_ES_UPNP 1 #define GNB_LOG_ID_ES_RESOLV 2 #define GNB_LOG_ID_ES_BROADCAST 3 #define GNB_LOG_ID_ES_DISCOVER_IN_LAN 4 #define DISCOVER_LAN_IN_BROADCAST_PORT 8998 #endif opengnb-ver1.6.0.a/src/es/gnb_es_upnp.c000077500000000000000000000211731500454252100177500ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 . */ #if defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) || defined(__OpenBSD__) #define __UNIX_LIKE_OS__ 1 #endif #include #include #include #include #include #include #include #ifdef __UNIX_LIKE_OS__ #include #endif #if defined(_WIN32) #undef _WIN32_WINNT #define _WIN32_WINNT 0x0600 #include #include #endif #include "gnb_conf_type.h" #include "gnb_node_type.h" #include "gnb_ctl_block.h" #include "gnb_time.h" #include "es/gnb_es_type.h" #include "miniupnpc.h" #include "natpmp.h" #include "upnpcommands.h" static void gnb_es_upnp_em(gnb_es_ctx *es_ctx, gnb_conf_t *conf, gnb_log_ctx_t *log){ const char *rootdescurl = NULL; struct UPNPDev *devlist = NULL; const char *multicastif = NULL; const char *minissdpdpath = ""; int localport = UPNP_LOCAL_PORT_ANY; int ipv6 = 0; unsigned char ttl = 2; const char *description = NULL; int error = 0; int r = 1; struct UPNPUrls urls; struct IGDdatas data; char lan_addr[64] = "unset"; char lan_addr_port[6]; //查询时用 char intClient[16]; char intPort[6]; char duration[16]; uint16_t last_extPort = 0; snprintf(lan_addr_port, 6, "%d", conf->udp4_ports[0]); uint16_t test_extPort; char ext_port_string[6]; char in_port_string[6]; if ( NULL == es_ctx->upnp_multicase_if ) { es_ctx->upnp_multicase_if = getenv("GNB_UPNP_MULTICAST_IF"); } multicastif = es_ctx->upnp_multicase_if; devlist = upnpDiscover(2000, multicastif, minissdpdpath, localport, ipv6, ttl, &error); GNB_LOG1(log, GNB_LOG_ID_ES_UPNP, "UPNPC Try to UPNP_GetValidIGD.\n"); if ( NULL == devlist ) { GNB_LOG1(log, GNB_LOG_ID_ES_UPNP, "UPNPC upnpDiscover get devlist faile! error=%d .....\n", error); return; } r = UPNP_GetValidIGD(devlist, &urls, &data, lan_addr, sizeof(lan_addr)); switch (r) { case 0: GNB_LOG1(log, GNB_LOG_ID_ES_UPNP, "UPNPC UPNP_GetValidIGD NO IGD found\n"); GNB_SLEEP_MILLISECOND(300 * 1000); return; case 1: GNB_LOG1(log, GNB_LOG_ID_ES_UPNP,"UPNPC Found valid IGD : %s\n", urls.controlURL); break; case 2: GNB_LOG1(log, GNB_LOG_ID_ES_UPNP, "UPNPC Found a (not connected?) IGD : %s\n", urls.controlURL); //有时得到 ipv6的 urls?然后失败 GNB_LOG1(log, GNB_LOG_ID_ES_UPNP, "UPNPC Trying to continue anyway\n"); break; case 3: GNB_LOG1(log, GNB_LOG_ID_ES_UPNP, "UPNPC UPnP device found. Is it an IGD ? : %s\n", urls.controlURL); GNB_LOG1(log, GNB_LOG_ID_ES_UPNP, "UPNPC Trying to continue anyway\n"); break; default: GNB_LOG1(log, GNB_LOG_ID_ES_UPNP, "UPNPC Found device (igd ?) : %s\n", urls.controlURL); GNB_LOG1(log, GNB_LOG_ID_ES_UPNP, "UPNPC Trying to continue anyway\n"); break; } if ( 0 == strncmp(lan_addr, "unset", 64) ) { goto next; } GNB_LOG1(log, GNB_LOG_ID_ES_UPNP, "UPNPC Local LAN ip address : %s\n", lan_addr); if ( 0 == strncmp(lan_addr, "unset", 64) ) { goto next; } int i; for ( i = 0; iudp4_socket_num; i++ ) { if( conf->udp4_ports[i] <= 1 || conf->udp4_ports[i] >= 65535 ) { continue; } snprintf(in_port_string, 6, "%d", conf->udp4_ports[i]); snprintf(ext_port_string, 6, "%d", conf->udp4_ext_ports[i]); r = UPNP_GetSpecificPortMappingEntry(urls.controlURL, data.first.servicetype, ext_port_string, "UDP", NULL/*remoteHost*/, intClient, intPort, NULL/*desc*/, NULL/*enabled*/, duration); if ( UPNPCOMMAND_SUCCESS == r) { if ( 0 == strncmp(lan_addr, intClient, 16) ) { GNB_LOG1(log, GNB_LOG_ID_ES_UPNP, "already redirected loacl[%s:%s] extPort[%d]\n", intClient, intPort, conf->udp4_ports[i]); } else { GNB_LOG1(log, GNB_LOG_ID_ES_UPNP, "already redirected other[%s:%s] extPort[%d]\n",intClient, intPort, conf->udp4_ports[i]); //conf->udp4_ext_ports[i] += 1; snprintf(ext_port_string, 6, "%d", conf->udp4_ext_ports[i]); } //续约 goto doPortMapping; } else { GNB_LOG1(log, GNB_LOG_ID_ES_UPNP, "UPNP_GetSpecificPortMappingEntry [%d]\n", r); } doPortMapping: r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype, ext_port_string, in_port_string, lan_addr, "GNB", "UDP", NULL, "3600"); if ( 0 == r ) { GNB_LOG1(log, GNB_LOG_ID_ES_UPNP, "now redirected [%s:%d] extPort[%d]\n", lan_addr, conf->udp4_ports[i], conf->udp4_ext_ports[i]); } else { GNB_LOG1(log, GNB_LOG_ID_ES_UPNP, "Port Mapping Error return[%d] [%s:%d] extPort[%d]\n", r, lan_addr, conf->udp4_ports[i], conf->udp4_ext_ports[i]); } } next: FreeUPNPUrls(&urls); freeUPNPDevlist(devlist); return; } int gnb_es_natpnpc(gnb_es_ctx *es_ctx, gnb_conf_t *conf, gnb_log_ctx_t *log){ int forcegw = 0; in_addr_t gateway = 0; natpmp_t natpmp; natpmpresp_t response; struct in_addr gateway_in_use; uint32_t lifetime = 3600; int i; int r; int sav_errno; int ret = 0; if ( NULL != es_ctx->upnp_gateway4 ) { inet_pton(AF_INET, es_ctx->upnp_gateway4, &gateway); forcegw = 1; } else { es_ctx->upnp_gateway4 = getenv("GNB_UPNP_GATEWAY"); if ( NULL != es_ctx->upnp_gateway4 ) { inet_pton(AF_INET, es_ctx->upnp_gateway4, &gateway); forcegw = 1; } } r = initnatpmp(&natpmp, forcegw, gateway); if ( r < 0 ) { ret = -1; goto finish; } gateway_in_use.s_addr = natpmp.gateway; r = sendpublicaddressrequest(&natpmp); if ( r < 0 ) { ret = -2; goto finish; } struct timeval timeout; fd_set fds; do { FD_ZERO(&fds); FD_SET(natpmp.s, &fds); getnatpmprequesttimeout(&natpmp, &timeout); r = select(FD_SETSIZE, &fds, NULL, NULL, &timeout); if ( r < 0 ) { ret = -3; goto finish; } r = readnatpmpresponseorretry(&natpmp, &response); sav_errno = errno; GNB_LOG1(log, GNB_LOG_ID_ES_UPNP, "readnatpmpresponseorretry returned %d (%s)\n", r, r==0?"OK":(r==NATPMP_TRYAGAIN?"TRY AGAIN":"FAILED")); if( r<0 && r!=NATPMP_TRYAGAIN ) { #ifdef ENABLE_STRNATPMPERR GNB_LOG1(log, GNB_LOG_ID_ES_UPNP, "readnatpmpresponseorretry() failed : %s\n", strnatpmperr(r)); #endif GNB_LOG1(log, GNB_LOG_ID_ES_UPNP, "errno=%d '%s'\n", sav_errno, strerror(sav_errno)); } } while (r==NATPMP_TRYAGAIN); if ( r < 0 ) { ret = -4; goto finish; } for ( i = 0; i < conf->udp4_socket_num; i++ ) { r = sendnewportmappingrequest(&natpmp, NATPMP_PROTOCOL_UDP, conf->udp4_ports[i], conf->udp4_ext_ports[i], lifetime); if ( r<0 ) { continue; } do { FD_ZERO(&fds); FD_SET(natpmp.s, &fds); getnatpmprequesttimeout(&natpmp, &timeout); select(FD_SETSIZE, &fds, NULL, NULL, &timeout); r = readnatpmpresponseorretry(&natpmp, &response); GNB_LOG1(log, GNB_LOG_ID_ES_UPNP, "readnatpmpresponseorretry returned %d (%s)\n", r, r==0?"OK":(r==NATPMP_TRYAGAIN?"TRY AGAIN":"FAILED")); } while(r==NATPMP_TRYAGAIN); } finish: r = closenatpmp(&natpmp); return ret; } void gnb_es_upnp(gnb_es_ctx *es_ctx, gnb_conf_t *conf, gnb_log_ctx_t *log){ int ret; ret = gnb_es_natpnpc(es_ctx, conf, log); if ( 0 == ret ) { GNB_LOG1(log, GNB_LOG_ID_ES_UPNP, "gnb_es_natpnpc finish upnp\n"); return; } GNB_LOG1(log, GNB_LOG_ID_ES_UPNP, "gnb_es_natpnpc ret=%d next gnb_es_upnp_em\n", ret); gnb_es_upnp_em(es_ctx, conf, log); } opengnb-ver1.6.0.a/src/freebsd/000077500000000000000000000000001500454252100163015ustar00rootroot00000000000000opengnb-ver1.6.0.a/src/freebsd/gnb_drv_freebsd.c000077500000000000000000000217411500454252100215700ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "gnb.h" #include "gnb_tun_drv.h" #include "gnb_payload16.h" void bind_socket_if(gnb_core_t *gnb_core){ if ( '\0' == gnb_core->conf->socket_ifname[0] ) { return; } int i; for ( i=0; i < gnb_core->conf->udp6_socket_num; i++ ) { setsockopt(gnb_core->udp_ipv6_sockets[i], SOL_SOCKET,IP_RECVIF, gnb_core->conf->socket_ifname, strlen(gnb_core->conf->socket_ifname)); } for ( i=0; i < gnb_core->conf->udp4_socket_num; i++ ) { setsockopt(gnb_core->udp_ipv4_sockets[i], SOL_SOCKET,IP_RECVIF, gnb_core->conf->socket_ifname, strlen(gnb_core->conf->socket_ifname)); } } static void if_up_script(gnb_core_t *gnb_core){ int ret; char cmd[1024]; snprintf(cmd,1024,"\"%s/scripts/%s\" > /dev/null 2>&1",gnb_core->conf->conf_dir,"if_up_freebsd.sh"); ret = system(cmd); if ( -1==ret || 0 ==ret ) { return; } return; } static void if_down_script(gnb_core_t *gnb_core){ int ret; char cmd[1024]; snprintf(cmd,1024,"\"%s/scripts/%s\" > /dev/null 2>&1",gnb_core->conf->conf_dir,"if_down_freebsd.sh"); ret = system(cmd); if ( -1==ret || 0 ==ret ) { return; } return; } /* set_route4的作用是 创建一条路由,以 tun ip 为 10.1.0.15 的local node为例: route -n add -net 10.1.0.0 -netmask 255.255.255.0 10.1.0.15 */ static void set_route4(gnb_core_t *gnb_core){ struct{ struct rt_msghdr hdr; struct sockaddr_in dst; struct sockaddr_in gateway; struct sockaddr_in mask; }rtmsg; uint32_t network_u32; int s; ssize_t wlen; //算出 节点的 ipv4 network network_u32 = gnb_core->local_node->tun_netmask_addr4.s_addr & gnb_core->local_node->tun_addr4.s_addr; s = socket(PF_ROUTE, SOCK_RAW, 0); if ( s < 0 ) { printf("error: socket\n"); return; } shutdown(s, SHUT_RD); bzero(&rtmsg, sizeof(rtmsg)); rtmsg.hdr.rtm_type = RTM_ADD; rtmsg.hdr.rtm_version = RTM_VERSION; rtmsg.hdr.rtm_addrs = 0; rtmsg.hdr.rtm_addrs |= RTA_DST; rtmsg.hdr.rtm_addrs |= RTA_GATEWAY; rtmsg.hdr.rtm_addrs |= RTA_NETMASK; rtmsg.hdr.rtm_flags = RTF_STATIC; rtmsg.hdr.rtm_flags |= RTF_GATEWAY; rtmsg.hdr.rtm_flags |= RTF_GATEWAY; rtmsg.dst.sin_len = sizeof(rtmsg.dst); rtmsg.dst.sin_family = AF_INET; rtmsg.dst.sin_addr.s_addr = network_u32; rtmsg.mask.sin_len = sizeof(rtmsg.mask); rtmsg.mask.sin_family = AF_INET; rtmsg.mask.sin_addr.s_addr = gnb_core->local_node->tun_netmask_addr4.s_addr; rtmsg.gateway.sin_len = sizeof(rtmsg.gateway); rtmsg.gateway.sin_family = AF_INET; rtmsg.gateway.sin_addr.s_addr = gnb_core->local_node->tun_addr4.s_addr; rtmsg.hdr.rtm_msglen = sizeof(rtmsg); wlen = write(s, &rtmsg, sizeof(rtmsg)); if ( -1==wlen ) { perror("#set_route4 write"); return; } return; } static void setifmtu(char *if_name,int mtu) { int socket_fd; struct ifreq ifr; memset(&ifr,0,sizeof(struct ifreq)); strncpy(ifr.ifr_name, if_name, IFNAMSIZ); ifr.ifr_mtu = mtu; if ( (socket_fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) { perror("socket "); } int ret = ioctl(socket_fd, SIOCSIFMTU, &ifr); if ( -1==ret ) { perror("ioctl"); } close(socket_fd); } static int set_addr4(char *if_name, char *ip, char *netmask) { struct addrinfo *srcres, *dstres, *netmaskres; struct ifaliasreq in_addreq; memset(&in_addreq, 0, sizeof(in_addreq)); getaddrinfo(ip, NULL, NULL, &srcres); getaddrinfo(ip, NULL, NULL, &dstres); getaddrinfo(netmask, NULL, NULL, &netmaskres); strncpy(in_addreq.ifra_name, if_name, IFNAMSIZ); memcpy(&in_addreq.ifra_addr, srcres->ai_addr, srcres->ai_addr->sa_len); memcpy(&in_addreq.ifra_dstaddr, dstres->ai_addr, dstres->ai_addr->sa_len); memcpy(&in_addreq.ifra_mask, netmaskres->ai_addr, netmaskres->ai_addr->sa_len); freeaddrinfo(srcres); freeaddrinfo(dstres); freeaddrinfo(netmaskres); int socket_fd; if ( (socket_fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) { perror("socket "); return -1; } int ret = ioctl(socket_fd, SIOCAIFADDR, &in_addreq); if ( -1==ret ) { perror("ioctl"); } close(socket_fd); return 0; } /* struct in6_aliasreq { char ifra_name[IFNAMSIZ]; struct sockaddr_in6 ifra_addr; struct sockaddr_in6 ifra_dstaddr; struct sockaddr_in6 ifra_prefixmask; int ifra_flags; struct in6_addrlifetime ifra_lifetime; int ifra_vhid; }; */ static int set_addr6(char *if_name, char *ip, char *netmask) { //不要设置 in6_addreq.ifra_dstaddr 成员, ioctl 会提示参数不正确 struct in6_aliasreq in6_addreq = { { 0 }, { 0 }, { 0 }, { 0 }, 0, { 0, 0, ND6_INFINITE_LIFETIME, ND6_INFINITE_LIFETIME } }; struct addrinfo *srcres, *netmaskres; struct addrinfo hints; bzero(&hints, sizeof(struct addrinfo)); hints.ai_family = AF_INET6; getaddrinfo(ip, NULL, &hints, &srcres); getaddrinfo(netmask, NULL, &hints, &netmaskres); strncpy(in6_addreq.ifra_name, if_name, IFNAMSIZ); memcpy(&in6_addreq.ifra_addr, srcres->ai_addr, srcres->ai_addr->sa_len); memcpy(&in6_addreq.ifra_prefixmask, netmaskres->ai_addr, netmaskres->ai_addr->sa_len); freeaddrinfo(srcres); freeaddrinfo(netmaskres); int socket_fd; if ( (socket_fd = socket(AF_INET6, SOCK_DGRAM, 0)) < 0 ) { perror("socket "); return -1; } int ret = ioctl(socket_fd, SIOCAIFADDR_IN6, &in6_addreq); if ( -1==ret ) { perror("ioctl"); } close(socket_fd); return ret; } int init_tun_freebsd(gnb_core_t *gnb_core){ gnb_core->tun_fd = -1; return 0; } static int open_tun_freebsd(gnb_core_t *gnb_core){ if ( -1 != gnb_core->tun_fd ) { return -1; } char name[PATH_MAX]; int t = 0; snprintf(name, PATH_MAX, "/dev/%s",gnb_core->ifname); gnb_core->tun_fd = open(name, O_RDWR); if ( -1==gnb_core->tun_fd ) { perror("open"); exit(1); } int flags; flags = fcntl(gnb_core->tun_fd, F_GETFD); flags |= FD_CLOEXEC; fcntl(gnb_core->tun_fd, F_SETFD, flags); /* TUNSIFHEAD The argument should be a pointer to an int; a non-zero value turns off ``link-layer'' mode, and enables ``multi-af'' mode, where every packet is preceded with a four byte address fam-ily. */ int on = 0; ioctl(gnb_core->tun_fd, TUNSIFHEAD, &on, sizeof(on)); set_addr4(gnb_core->ifname, GNB_ADDR4STR_PLAINTEXT1(&gnb_core->local_node->tun_addr4), GNB_ADDR4STR_PLAINTEXT2(&gnb_core->local_node->tun_netmask_addr4)); set_addr6(gnb_core->ifname, GNB_ADDR6STR_PLAINTEXT1(&gnb_core->local_node->tun_ipv6_addr), "FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:0000:0000"); set_route4(gnb_core); setifmtu(gnb_core->ifname, gnb_core->conf->mtu); if_up_script(gnb_core); return 0; } static int read_tun_freebsd(gnb_core_t *gnb_core, void *buf, size_t buf_size){ ssize_t rlen; rlen = read(gnb_core->tun_fd, buf, buf_size); return rlen; } static int write_tun_freebsd(gnb_core_t *gnb_core, void *buf, size_t buf_size){ ssize_t wlen; wlen = write(gnb_core->tun_fd, buf, buf_size); return wlen; } static int close_tun_freebsd(gnb_core_t *gnb_core){ if_down_script(gnb_core); close(gnb_core->tun_fd); return 0; } static int release_tun_freebsd(gnb_core_t *gnb_core){ return 0; } gnb_tun_drv_t gnb_tun_drv_freebsd = { init_tun_freebsd, open_tun_freebsd, read_tun_freebsd, write_tun_freebsd, close_tun_freebsd, release_tun_freebsd }; opengnb-ver1.6.0.a/src/gnb.h000077500000000000000000000100051500454252100156050ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 . */ #ifndef GNB_H #define GNB_H #include "gnb_platform.h" #ifdef __UNIX_LIKE_OS__ #include #include #include #include #include #endif #ifdef _WIN32 #undef _WIN32_WINNT #define _WIN32_WINNT 0x0600 #define _POSIX #include #include #endif #include "gnb_alloc.h" #include "gnb_hash32.h" #include "gnb_payload16.h" #include "gnb_node_type.h" #include "gnb_core_frame_type_defs.h" #include "gnb_tun_drv.h" #include "gnb_pf.h" #include "gnb_address.h" #include "gnb_worker.h" #include "gnb_conf_type.h" #include "gnb_node_type.h" #include "gnb_ctl_block.h" #include "gnb_log.h" typedef struct _gnb_core_t{ gnb_heap_t *heap; char *ifname; char *if_device_string; gnb_node_t *local_node; gnb_node_t *select_fwd_node; gnb_node_ring_t index_node_ring; gnb_node_ring_t fwd_node_ring; gnb_address_ring_t index_address_ring; gnb_address_ring_t fwdu0_address_ring; int time_seed_update_factor; unsigned char time_seed[64]; unsigned char *ed25519_private_key; unsigned char *ed25519_public_key; gnb_conf_t *conf; uint64_t node_nums; gnb_hash32_map_t *uuid_node_map; //以节点的uuid64作为key的 node 表 gnb_hash32_map_t *ipv4_node_map; gnb_hash32_map_t *subneta_node_map; gnb_hash32_map_t *subnetb_node_map; gnb_hash32_map_t *subnetc_node_map; //不同主模块可以按照模块内部的方式使用这些表 //由使用的相关联的模块来初始化这两组表 //这组张表是整型为key gnb_hash32_map_t *int32_map0; gnb_hash32_map_t *int32_map1; gnb_hash32_map_t *int32_map2; //这组表是整型为 string gnb_hash32_map_t *string_map0; gnb_hash32_map_t *string_map1; gnb_hash32_map_t *string_map2; int tun_fd; int udp_ipv6_sockets[GNB_MAX_UDP6_SOCKET_NUM]; int udp_ipv4_sockets[GNB_MAX_UDP4_SOCKET_NUM]; int loop_flag; gnb_tun_drv_t *drv; gnb_payload16_t *inet_payload0; gnb_payload16_t *tun_payload0; gnb_payload16_t *inet_payload; gnb_payload16_t *tun_payload; void *platform_ctx; gnb_worker_t *primary_worker; gnb_worker_t *node_worker; gnb_worker_t *index_worker; gnb_worker_t *index_service_worker; gnb_worker_t *detect_worker; gnb_worker_t *upnp_worker; gnb_worker_ring_t *pf_worker_ring; struct timeval now_timeval; uint64_t now_time_sec; uint64_t now_time_usec; //把 tun 数据读入 payload 时给pf过程构建的frame首部预留的空间 //这样构建的 payload 可以直接发送出去,尽量避免了pf过程发生内存拷贝 size_t tun_payload_offset; //route ip frame 类型的 paylaod 的 head size size_t route_frame_head_size; gnb_ctl_block_t *ctl_block; gnb_log_ctx_t *log; }gnb_core_t; #define GNB_ADDR_TYPE_NONE (0x0) #define GNB_ADDR_TYPE_IPV4 (0x1) #define GNB_ADDR_TYPE_IPV6 (0x1 << 1) #define GNB_LOG_ID_CORE 0 #define GNB_LOG_ID_PF 1 #define GNB_LOG_ID_MAIN_WORKER 2 #define GNB_LOG_ID_NODE_WORKER 3 #define GNB_LOG_ID_INDEX_WORKER 4 #define GNB_LOG_ID_INDEX_SERVICE_WORKER 5 #define GNB_LOG_ID_DETECT_WORKER 6 #define GNB_VERSION_STRING "GNB version Dev 1.6.0.a protocol version 1.6.0" #define GNB_COPYRIGHT_STRING "Copyright (C) 2019 gnbdev" #define GNB_URL_STRING "https://github.com/gnbdev/opengnb" #endif opengnb-ver1.6.0.a/src/gnb_address.c000077500000000000000000000321131500454252100173110ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 #include #include #include #include "gnb_platform.h" #ifdef __UNIX_LIKE_OS__ #include #include #define __USE_MISC 1 #include #endif #ifdef _WIN32 #undef _WIN32_WINNT #define _WIN32_WINNT 0x0600 #include #include //#define __USE_MISC 1 //#include #define in_addr_t uint32_t #define _POSIX #define __USE_MINGW_ALARM #endif #include "gnb_address.h" uint8_t gnb_addr_secure = 0; unsigned long long gnb_htonll(unsigned long long val){ #if __BYTE_ORDER__==__ORDER_LITTLE_ENDIAN__ uint64_t rv= 0; uint8_t x= 0; for (x= 0; x < 8; x++) { rv= (rv << 8) | (val & 0xff); val >>= 8; } return rv; #endif #if __BYTE_ORDER__==__ORDER_BIG_ENDIAN__ return val; #endif } unsigned long long gnb_ntohll(unsigned long long val){ #if __BYTE_ORDER__==__ORDER_LITTLE_ENDIAN__ uint64_t rv= 0; uint8_t x= 0; for (x= 0; x < 8; x++) { rv= (rv << 8) | (val & 0xff); val >>= 8; } return rv; #endif #if __BYTE_ORDER__==__ORDER_BIG_ENDIAN__ return val; #endif } char get_netmask_class(uint32_t addr4){ if ( !(~(IN_CLASSA_NET) & ntohl(addr4)) ) { return 'a'; } if ( !(~(IN_CLASSB_NET) & ntohl(addr4)) ) { return 'b'; } if ( !(~(IN_CLASSC_NET) & ntohl(addr4)) ) { return 'c'; } return 'n'; } gnb_address_list_t* gnb_create_address_list(size_t size){ gnb_address_list_t *address_list; address_list = (gnb_address_list_t *)malloc( sizeof(gnb_address_list_t) + sizeof(gnb_address_t)*size ); memset(address_list, 0, sizeof(gnb_address_list_t) + sizeof(gnb_address_t)*size); address_list->size = size; address_list->num = 0; return address_list; } void gnb_address_list_release(gnb_address_list_t *address_list){ free(address_list); } int gnb_address_list_find(gnb_address_list_t *address_list, gnb_address_t *address) { int i; for ( i=0; i < address_list->num; i++ ) { if ( address->type != address_list->array[i].type ) { continue; } if ( address->port != address_list->array[i].port ) { continue; } if ( AF_INET == address->type && 0 == memcmp(address_list->array[i].m_address4, address->m_address4, 4) ) { return i; } if ( AF_INET6 == address->type && 0 == memcmp(address_list->array[i].m_address6, address->m_address6, 16)) { return i; } } return -1; } int gnb_address_list_get_free_idx(gnb_address_list_t *address_list) { int free_idx = 0; uint64_t min_ts_sec = address_list->array[free_idx].ts_sec; int i; for ( i=0; i < address_list->size; i++ ) { if ( 0 == address_list->array[i].port ) { free_idx = i; break; } if ( address_list->array[i].ts_sec <= min_ts_sec ) { min_ts_sec = address_list->array[i].ts_sec; free_idx = i; } } return free_idx; } void gnb_address_list_update(gnb_address_list_t *address_list, gnb_address_t *address){ int idx = 0; idx = gnb_address_list_find(address_list, address); if ( -1 != idx ) { goto finish; } idx = gnb_address_list_get_free_idx(address_list); finish: if ( 0 == address_list->array[idx].port ) { if ( address_list->num < address_list->size ) { address_list->num += 1; } else if (address_list->num > address_list->size) { address_list->num = address_list->size; } } memcpy( &address_list->array[idx], address, sizeof(gnb_address_t) ); } void gnb_set_address4(gnb_address_t *address, struct sockaddr_in *in){ address->type = AF_INET; address->port = in->sin_port; memcpy(&address->address.addr4, &in->sin_addr.s_addr ,sizeof(struct in_addr)); } void gnb_set_address6(gnb_address_t *address, struct sockaddr_in6 *in6){ address->type = AF_INET6; address->port = in6->sin6_port; memcpy(&address->address.addr6, &in6->sin6_addr ,sizeof(struct in6_addr)); } char * gnb_get_address4string(void *byte4, char *dest, uint8_t addr_secure){ inet_ntop(AF_INET, byte4, dest, INET_ADDRSTRLEN); char *p; if (addr_secure) { p = dest; while( '\0' != *p ) { if ( '.' == *p ) { break; } *p = '*'; p++; } } return dest; } char * gnb_get_address6string(void *byte16, char *dest, uint8_t addr_secure){ inet_ntop(AF_INET6, byte16, dest, INET6_ADDRSTRLEN); char *p; if (addr_secure) { p = dest; while ( '\0' != *p ) { if ( ':' == *p ) { break; } *p = '*'; p++; } } return dest; } char * gnb_get_socket4string(struct sockaddr_in *in, char *dest, uint8_t addr_secure){ char buf[INET_ADDRSTRLEN]; inet_ntop(AF_INET, &in->sin_addr, buf, INET_ADDRSTRLEN); snprintf(dest, GNB_IP4_PORT_STRING_SIZE,"%s:%d",buf,ntohs(in->sin_port)); char *p; if (addr_secure) { p = dest; while ( '\0' != *p ) { if ( '.' == *p ) { break; } *p = '*'; p++; } } return dest; } char * gnb_get_socket6string(struct sockaddr_in6 *in6, char *dest, uint8_t addr_secure){ char buf[INET6_ADDRSTRLEN]; inet_ntop(AF_INET6, &in6->sin6_addr, buf, INET6_ADDRSTRLEN); snprintf(dest, GNB_IP6_PORT_STRING_SIZE,"[%s:%d]",buf,ntohs(in6->sin6_port)); char *p; if ( addr_secure ) { p = dest+1; while ( '\0' != *p ) { if ( ':' == *p ) { break; } *p = '*'; p++; } } return dest; } char * gnb_get_sockaddress_string(gnb_sockaddress_t *sockaddress, char *dest, uint8_t addr_secure){ if ( AF_INET6 == sockaddress->addr_type ) { dest = gnb_get_socket6string(&sockaddress->addr.in6,dest,addr_secure); } else if ( AF_INET == sockaddress->addr_type ) { dest = gnb_get_socket4string(&sockaddress->addr.in,dest,addr_secure); } return dest; } char * gnb_get_ip_port_string(gnb_address_t *address, char *dest, uint8_t addr_secure){ char buf[INET6_ADDRSTRLEN]; char *p; p = dest; if ( AF_INET6 == address->type ) { inet_ntop(AF_INET6, &address->address.addr6, buf, INET6_ADDRSTRLEN); snprintf(dest, GNB_IP6_PORT_STRING_SIZE,"[%s:%d]",buf,ntohs(address->port)); p++; } else if ( AF_INET == address->type ) { inet_ntop(AF_INET, &address->address.addr4, buf, INET_ADDRSTRLEN); snprintf(dest, GNB_IP6_PORT_STRING_SIZE,"%s:%d",buf,ntohs(address->port)); } else { snprintf(dest, GNB_IP6_PORT_STRING_SIZE,"NONE_ADDRESS"); } if ( addr_secure ) { while ( '\0' != *p ) { if ( '.' == *p || ':' == *p ) { break; } *p = '*'; p++; } } return dest; } int gnb_cmp_sockaddr_in6(struct sockaddr_in6 *in1, struct sockaddr_in6 *in2){ if ( in1->sin6_port != in2->sin6_port ) { return 1; } if ( 0 != memcmp( &in1->sin6_addr, &in2->sin6_addr, 16) ) { return 2; } return 0; } int gnb_cmp_sockaddr_in(struct sockaddr_in *in1, struct sockaddr_in *in2){ if ( in1->sin_port != in2->sin_port ) { return 1; } if ( in1->sin_addr.s_addr != in2->sin_addr.s_addr ) { return 2; } return 0; } void gnb_set_sockaddress4(gnb_sockaddress_t *sockaddress, int protocol, const char *host, int port){ sockaddress->addr_type = AF_INET; if ( GNB_PROTOCOL_TCP == protocol ) { sockaddress->protocol = SOCK_STREAM; } else if ( GNB_PROTOCOL_UDP == protocol ) { sockaddress->protocol = SOCK_DGRAM; } else { sockaddress->protocol = SOCK_DGRAM; } memset(&sockaddress->m_in4,0, sizeof(struct sockaddr_in)); sockaddress->m_in4.sin_family = AF_INET; if ( NULL != host ) { inet_pton(AF_INET, host, (struct in_addr *)&sockaddress->m_in4.sin_addr.s_addr); } else { sockaddress->m_in4.sin_addr.s_addr = htonl(INADDR_ANY); } sockaddress->m_in4.sin_port = htons(port); sockaddress->socklen = sizeof(struct sockaddr_in); } void gnb_set_sockaddress6(gnb_sockaddress_t *sockaddress, int protocol, const char *host, int port){ sockaddress->addr_type = AF_INET6; if ( GNB_PROTOCOL_TCP == protocol ) { sockaddress->protocol = SOCK_STREAM; } else if ( GNB_PROTOCOL_UDP == protocol ) { sockaddress->protocol = SOCK_DGRAM; } else { sockaddress->protocol = SOCK_DGRAM; } memset(&sockaddress->m_in6,0, sizeof(struct sockaddr_in6)); sockaddress->m_in6.sin6_family = AF_INET6; if ( NULL != host ) { inet_pton( AF_INET6, host, &sockaddress->m_in6.sin6_addr); } else { sockaddress->m_in6.sin6_addr = in6addr_any; } sockaddress->m_in6.sin6_port = htons(port); sockaddress->socklen = sizeof(struct sockaddr_in6); } gnb_address_t gnb_get_address4_from_string(const char *sockaddress4_string){ gnb_address_t address; memset(&address,0,sizeof(gnb_address_t)); unsigned long int ul; char sockaddress4_string_copy[16]; int sockaddress4_string_len = strlen(sockaddress4_string); memcpy(sockaddress4_string_copy, sockaddress4_string, sockaddress4_string_len); int i; char *p = sockaddress4_string_copy; for ( i=0; inum ) { goto update_fifo; } idx = gnb_address_list_find(address_list, address); if ( idx >= 0 ) { address_list->array[idx].ts_sec = address->ts_sec; return; } update_fifo: switch (address_list->num) { case 3: memcpy( &address_list->array[2], &address_list->array[1], sizeof(gnb_address_t) ); memcpy( &address_list->array[1], &address_list->array[0], sizeof(gnb_address_t) ); memcpy( &address_list->array[0], address, sizeof(gnb_address_t) ); break; case 2: memcpy( &address_list->array[2], &address_list->array[1], sizeof(gnb_address_t) ); memcpy( &address_list->array[1], &address_list->array[0], sizeof(gnb_address_t) ); memcpy( &address_list->array[0], address, sizeof(gnb_address_t) ); address_list->num = 3; break; case 1: memcpy( &address_list->array[1], &address_list->array[0], sizeof(gnb_address_t) ); memcpy( &address_list->array[0], address, sizeof(gnb_address_t) ); address_list->num = 2; break; case 0: default: memcpy( &address_list->array[0], address, sizeof(gnb_address_t) ); address_list->num = 1; break; } } int gnb_determine_subnet6_prefixlen96(struct in6_addr addr6_a, struct in6_addr addr6_b) { int ret; addr6_a.s6_addr[12] = 0; addr6_a.s6_addr[13] = 0; addr6_a.s6_addr[14] = 0; addr6_a.s6_addr[15] = 0; addr6_b.s6_addr[12] = 0; addr6_b.s6_addr[13] = 0; addr6_b.s6_addr[14] = 0; addr6_b.s6_addr[15] = 0; /* rfc3542 This macro returns non-zero if the addresses are equal; otherwise it returns zero. */ ret = IN6_ARE_ADDR_EQUAL( &addr6_a, &addr6_b ); return ret; } int gnb_determine_subnet4(struct in_addr addr4_a, struct in_addr addr4_b, struct in_addr netmask) { in_addr_t ipv4_network_a; in_addr_t ipv4_network_b; ipv4_network_a = addr4_a.s_addr & netmask.s_addr; ipv4_network_b = addr4_b.s_addr & netmask.s_addr; if ( ipv4_network_a == ipv4_network_b ) { return 1; } return 0; } opengnb-ver1.6.0.a/src/gnb_address.h000077500000000000000000000123021500454252100173140ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 . */ #ifndef GNB_ADDRESS_H #define GNB_ADDRESS_H #include "gnb_address_type.h" #define GNB_ADDRESS_LIFE_TIME_TS_SEC 120 #define GNB_ADDRESS_AVAILABLE(address,now_sec) (now_sec - address->ts_sec) < GNB_ADDRESS_LIFE_TIME_TS_SEC ? 1:0 /* 当 gnb_addr_secure 为非零时将不输出的完整的ip地址 */ extern uint8_t gnb_addr_secure; unsigned long long gnb_ntohll(unsigned long long val); unsigned long long gnb_htonll(unsigned long long val); char get_netmask_class(uint32_t addr4); gnb_address_list_t* gnb_create_address_list(size_t size); void gnb_address_list_release(gnb_address_list_t *address_list); //返回 -1 没有找到, >0 为 address 在 list 中的索引编号 int gnb_address_list_find(gnb_address_list_t *address_list, gnb_address_t *address); //把 address 放进列表中一个空的项里 void gnb_address_list_update(gnb_address_list_t *address_list, gnb_address_t *address); void gnb_set_address4(gnb_address_t *address, struct sockaddr_in *in); void gnb_set_address6(gnb_address_t *address, struct sockaddr_in6 *in6); static char gnb_static_ip_port_string_buffer1[GNB_IP6_PORT_STRING_SIZE]; static char gnb_static_ip_port_string_buffer2[GNB_IP6_PORT_STRING_SIZE]; static char gnb_static_ip_port_string_buffer3[GNB_IP6_PORT_STRING_SIZE]; char * gnb_get_ip_port_string(gnb_address_t *address, char *dest, uint8_t addr_secure); #define GNB_IP_PORT_STR1(address) gnb_get_ip_port_string(address,gnb_static_ip_port_string_buffer1,gnb_addr_secure) #define GNB_IP_PORT_STR2(address) gnb_get_ip_port_string(address,gnb_static_ip_port_string_buffer2,gnb_addr_secure) char * gnb_get_address4string(void *byte4, char *dest, uint8_t addr_secure); char * gnb_get_address6string(void *byte16, char *dest, uint8_t addr_secure); #define GNB_ADDR4STR1(byte4) gnb_get_address4string(byte4,gnb_static_ip_port_string_buffer1,gnb_addr_secure) #define GNB_ADDR4STR2(byte4) gnb_get_address4string(byte4,gnb_static_ip_port_string_buffer2,gnb_addr_secure) #define GNB_ADDR6STR1(byte16) gnb_get_address6string(byte16,gnb_static_ip_port_string_buffer1,gnb_addr_secure) #define GNB_ADDR6STR2(byte16) gnb_get_address6string(byte16,gnb_static_ip_port_string_buffer2,gnb_addr_secure) #define GNB_ADDR4STR_PLAINTEXT1(byte4) gnb_get_address4string(byte4,gnb_static_ip_port_string_buffer1,0) #define GNB_ADDR4STR_PLAINTEXT2(byte4) gnb_get_address4string(byte4,gnb_static_ip_port_string_buffer2,0) #define GNB_ADDR6STR_PLAINTEXT1(byte16) gnb_get_address6string(byte16,gnb_static_ip_port_string_buffer1,0) #define GNB_ADDR6STR_PLAINTEXT2(byte16) gnb_get_address6string(byte16,gnb_static_ip_port_string_buffer2,0) char * gnb_get_socket4string(struct sockaddr_in *in, char *dest, uint8_t addr_secure); char * gnb_get_socket6string(struct sockaddr_in6 *in6, char *dest, uint8_t addr_secure); #define GNB_SOCKADDR4STR1(in) gnb_get_socket4string(in, gnb_static_ip_port_string_buffer1,gnb_addr_secure) #define GNB_SOCKADDR6STR1(in6) gnb_get_socket6string(in6,gnb_static_ip_port_string_buffer1,gnb_addr_secure) #define GNB_SOCKADDR4STR2(in) gnb_get_socket4string(in, gnb_static_ip_port_string_buffer2,gnb_addr_secure) #define GNB_SOCKADDR6STR2(in6) gnb_get_socket6string(in6,gnb_static_ip_port_string_buffer2,gnb_addr_secure) #define GNB_SOCKADDR4STR3(in) gnb_get_socket4string(in, gnb_static_ip_port_string_buffer3,gnb_addr_secure) #define GNB_SOCKADDR6STR3(in6) gnb_get_socket6string(in6,gnb_static_ip_port_string_buffer3,gnb_addr_secure) char * gnb_get_sockaddress_string(gnb_sockaddress_t *sockaddress, char *dest, uint8_t addr_secure); #define GNB_SOCKETADDRSTR1(sockaddress) gnb_get_sockaddress_string(sockaddress,gnb_static_ip_port_string_buffer1,gnb_addr_secure) #define GNB_SOCKETADDRSTR2(sockaddress) gnb_get_sockaddress_string(sockaddress,gnb_static_ip_port_string_buffer2,gnb_addr_secure) int gnb_cmp_sockaddr_in6(struct sockaddr_in6 *in1, struct sockaddr_in6 *in2); int gnb_cmp_sockaddr_in(struct sockaddr_in *in1, struct sockaddr_in *in2); #define GNB_PROTOCOL_UDP 0x1 #define GNB_PROTOCOL_TCP 0x2 void gnb_set_sockaddress4(gnb_sockaddress_t *sockaddress, int protocol, const char *host, int port); void gnb_set_sockaddress6(gnb_sockaddress_t *sockaddress, int protocol, const char *host, int port); gnb_address_t gnb_get_address4_from_string(const char *sockaddress4_string); void gnb_address_list3_fifo(gnb_address_list_t *address_list, gnb_address_t *address); /* 只判断 prefixlen=96 的子网 */ int gnb_determine_subnet6_prefixlen96(struct in6_addr addr6_a, struct in6_addr addr6_b); int gnb_determine_subnet4(struct in_addr addr4_a, struct in_addr addr4_b, struct in_addr netmask); #endif opengnb-ver1.6.0.a/src/gnb_address_type.h000077500000000000000000000042501500454252100203600ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 . */ #ifndef GNB_ADDRESS_TYPE_H #define GNB_ADDRESS_TYPE_H #include "gnb_platform.h" #ifdef __UNIX_LIKE_OS__ #include #include #endif #ifdef _WIN32 #include #include #endif #include #include #define GNB_IP6_PORT_STRING_SIZE ( 46 + 2 + sizeof("65535") + 1 ) #define GNB_IP4_PORT_STRING_SIZE ( 16 + 1 + sizeof("65535") + 1 ) #pragma pack(push, 1) typedef struct _gnb_address_t{ int type; //AF_INET AF_INET6 //更新该地址的 socket 索引 uint8_t socket_idx; //最后更新时间 uint64_t ts_sec; //延时,经过 ping pong 后算出 uint64_t latency_usec; union{ uint8_t addr4[4]; uint8_t addr6[16]; }address; #define m_address4 address.addr4 #define m_address6 address.addr6 //网络字节序 uint16_t port; }gnb_address_t; #pragma pack(pop) typedef struct _gnb_address_list_t{ size_t size; size_t num; uint64_t update_sec; gnb_address_t array[0]; }gnb_address_list_t; #define GNB_MAX_ADDR_RING 128 typedef struct _gnb_address_ring_t{ int cur_index; gnb_address_list_t *address_list; }gnb_address_ring_t; typedef struct _gnb_sockaddress_t{ int addr_type; // AF_INET AF_INET6 int protocol; //SOCK_STREAM SOCK_DGRAM union{ struct sockaddr_in in; struct sockaddr_in6 in6; }addr; #define m_in4 addr.in #define m_in6 addr.in6 //在确定 addr_type 是 AF_INET 或 AF_INET6 后,就能确定这个长度了,可以去掉这个成员 socklen_t socklen; }gnb_sockaddress_t; #endif opengnb-ver1.6.0.a/src/gnb_alloc.c000077500000000000000000000076641500454252100167730ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 #include #include "gnb_alloc.h" #ifndef offsetof #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) #endif #ifndef container_of #define container_of(ptr, type, member) ({ \ const typeof( ((type *)0)->member ) *__mptr = (ptr); \ (type *)( (char *)__mptr - offsetof(type,member) );}) #endif typedef struct _gnb_heap_fragment_t{ uint32_t size; uint32_t idx; unsigned char block[0]; }gnb_heap_fragment_t; gnb_heap_t* gnb_heap_create(uint32_t max_fragment){ gnb_heap_t *gnb_heap = (gnb_heap_t *)malloc( sizeof(gnb_heap_t) + sizeof(gnb_heap_fragment_t) * max_fragment ); if ( NULL==gnb_heap ) { return NULL; } memset(gnb_heap, 0, sizeof(gnb_heap_t)); gnb_heap->max_fragment = max_fragment; gnb_heap->fragment_nums = 0; return gnb_heap; } void* gnb_heap_alloc(gnb_heap_t *gnb_heap, uint32_t size){ if ( 0 == size ) { return NULL; } if ( gnb_heap->max_fragment == gnb_heap->fragment_nums ) { printf("gnb heap is full\n"); exit(1); return NULL; } if ( size > (uint32_t)(1024l * 1024l * 1024l) - 1 ) { return NULL; } gnb_heap_fragment_t *fragment = malloc( sizeof(gnb_heap_fragment_t) + sizeof(unsigned char) * size ); if ( NULL == fragment ) { return NULL; } fragment->idx = gnb_heap->fragment_nums; gnb_heap->fragment_list[ gnb_heap->fragment_nums ] = fragment; gnb_heap->fragment_nums++; gnb_heap->alloc_byte += size; gnb_heap->ralloc_byte += sizeof(gnb_heap_fragment_t)+size; return (void *)fragment->block; } void gnb_heap_free(gnb_heap_t *gnb_heap, void *p){ gnb_heap_fragment_t *fragment; if ( 0 == gnb_heap->fragment_nums ) { //发生错误了 return; } if ( NULL == p ) { return; } fragment = container_of(p, struct _gnb_heap_fragment_t, block); gnb_heap_fragment_t *last_fragment = gnb_heap->fragment_list[gnb_heap->fragment_nums - 1]; if ( fragment->idx > (gnb_heap->max_fragment-1) ) { //发生错误了 return; } if ( last_fragment->idx > (gnb_heap->max_fragment-1) ) { //发生错误了 return; } if ( 1 == gnb_heap->fragment_nums ) { if ( fragment->idx != last_fragment->idx ) { //发生错误了 return; } goto finish; } if ( last_fragment->idx == fragment->idx ) { goto finish; } gnb_heap->alloc_byte -= fragment->size; gnb_heap->ralloc_byte -= (sizeof(gnb_heap_fragment_t)+fragment->size); last_fragment->idx = fragment->idx; gnb_heap->fragment_list[last_fragment->idx] = last_fragment; finish: gnb_heap->fragment_nums--; free(fragment); } void gnb_heap_clean(gnb_heap_t *gnb_heap){ int i; if ( 0 == gnb_heap->fragment_nums ) { return; } for ( i=0; i < gnb_heap->fragment_nums; i++ ) { free(gnb_heap->fragment_list[i]); } gnb_heap->fragment_nums = 0; gnb_heap->alloc_byte = 0; gnb_heap->ralloc_byte = 0; } void gnb_heap_release(gnb_heap_t *gnb_heap){ gnb_heap_clean(gnb_heap); free(gnb_heap); } opengnb-ver1.6.0.a/src/gnb_alloc.h000077500000000000000000000023641500454252100167700ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 . */ #ifndef GNB_ALLOC_H #define GNB_ALLOC_H #include #include typedef struct _gnb_heap_fragment_t gnb_heap_fragment_t; typedef struct _gnb_heap_t{ uint32_t max_fragment; uint32_t fragment_nums; uint32_t alloc_byte; uint32_t ralloc_byte; gnb_heap_fragment_t *fragment_list[0]; }gnb_heap_t; gnb_heap_t* gnb_heap_create(uint32_t max_fragment); void* gnb_heap_alloc(gnb_heap_t *gnb_heap, uint32_t size); void gnb_heap_free(gnb_heap_t *gnb_heap, void *p); void gnb_heap_clean(gnb_heap_t *gnb_heap); void gnb_heap_release(gnb_heap_t *gnb_heap); #endif opengnb-ver1.6.0.a/src/gnb_arg_list.c000077500000000000000000000110511500454252100174660ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 #include #include "gnb_arg_list.h" gnb_arg_list_t *gnb_arg_list_init(int size){ gnb_arg_list_t *arg_list = (gnb_arg_list_t *)malloc( sizeof(gnb_arg_list_t) + sizeof(char *) * size ); arg_list->size = size; arg_list->argc = 0; return arg_list; } void gnb_arg_list_release(gnb_arg_list_t *arg_list){ int i; if ( arg_list->argc > 0 ) { for ( i=0; iargc; i++ ) { free(arg_list->argv[i]); } } free(arg_list); } int gnb_arg_append(gnb_arg_list_t *arg_list,const char *arg){ if ( arg_list->argc >= arg_list->size ) { return -1; } arg_list->argv[arg_list->argc] = strdup(arg); arg_list->argc++; return 0; } int gnb_arg_list_to_string(gnb_arg_list_t *arg_list, char *string, size_t string_len){ int i; size_t argv_len; char *p = string; size_t copied_len = 0; for ( i=0; i < arg_list->argc; i++ ) { argv_len = strlen( arg_list->argv[i] ); if ( (copied_len + argv_len) > string_len ) { break; } strncpy(p, arg_list->argv[i], string_len-copied_len); p += argv_len; *p = ' '; p += 1; copied_len += (argv_len+1); } if ( p == string ) { return -1; } *(p-1) = '\0'; return 0; } #define SPACE_SEPARATOR 0 #define SINGLE_QUOTES_SEPARATOR 1 #define DOUBLE_QUOTES_SEPARATOR 2 #define ARG_SEPARATOR 0 #define ARG_STRING 1 gnb_arg_list_t *gnb_arg_string_to_list(char *string, int num){ int status = ARG_SEPARATOR; int separator = SPACE_SEPARATOR; char *arg; char *arg_p; arg = malloc(GNB_ARG_MAX_SIZE); arg_p = arg; char *p; p = (char *)string; gnb_arg_list_t *arg_list = gnb_arg_list_init(num); int c = 0; while (*p) { if ( c>=GNB_ARG_STRING_MAX_SIZE ) { break; } if ( ' ' == *p ) { if ( ARG_STRING == status && SPACE_SEPARATOR == separator ) { *arg_p = '\0'; gnb_arg_append(arg_list,arg); arg_p = arg; status = ARG_SEPARATOR; goto next; } if ( ARG_STRING == status && ( SINGLE_QUOTES_SEPARATOR == separator || DOUBLE_QUOTES_SEPARATOR == separator ) ) { *arg_p = *p; arg_p++; status = ARG_SEPARATOR; goto next; } } if ( '\'' == *p ) { if ( SPACE_SEPARATOR == separator ) { separator = SINGLE_QUOTES_SEPARATOR; status = ARG_STRING; goto next; } if ( ARG_STRING == status && SINGLE_QUOTES_SEPARATOR == separator ) { *arg_p = '\0'; gnb_arg_append(arg_list,arg); arg_p = arg; separator = SPACE_SEPARATOR; status = ARG_SEPARATOR; goto next; } } if ( ' ' != *p && SPACE_SEPARATOR == separator ) { status = ARG_STRING; *arg_p = *p; arg_p++; goto next; } else if ( SPACE_SEPARATOR != separator ) { status = ARG_STRING; *arg_p = *p; arg_p++; goto next; } next: p++; c++; }; if ( arg_p != arg ) { *arg_p = '\0'; gnb_arg_append(arg_list,arg); } free(arg); return arg_list; } opengnb-ver1.6.0.a/src/gnb_arg_list.h000077500000000000000000000023571500454252100175040ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 . */ #ifndef GNB_ARG_LIST_H #define GNB_ARG_LIST_H #include #define GNB_ARG_STRING_MAX_SIZE 1024*4 #define GNB_ARG_MAX_SIZE 1024 typedef struct _gnb_arg_list_t { size_t size; int argc; char *argv[0]; }gnb_arg_list_t; gnb_arg_list_t *gnb_arg_list_init(int size); void gnb_arg_list_release(gnb_arg_list_t *arg_list); int gnb_arg_append(gnb_arg_list_t *arg_list,const char *arg); int gnb_arg_list_to_string(gnb_arg_list_t *arg_list, char *string, size_t string_len); gnb_arg_list_t *gnb_arg_string_to_list(char *string, int num); #endif opengnb-ver1.6.0.a/src/gnb_argv.c000077500000000000000000001240721500454252100166310ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 #include #include #include #include #include #include "gnb.h" #include "gnb_address_type.h" #include "gnb_keys.h" #include "gnb_dir.h" #include "gnb_arg_list.h" #include "gnb_config_lite.h" extern gnb_conf_ext_lite_t gnb_conf_ext_lite; void show_description(); static void show_useage(int argc,char *argv[]); int check_listen_string(char *listen_string); void gnb_setup_listen_addr_port(char *listen_address6_string, uint16_t *port_ptr, char *sockaddress_string, int addr_type); void gnb_setup_es_argv(char *es_argv_string); #define GNB_OPT_INIT 0x91 #define SET_ADDR_SECURE (GNB_OPT_INIT + 1) #define SET_STANDARD_FORWARDING (GNB_OPT_INIT + 4) #define SET_DIRECT_FORWARDING (GNB_OPT_INIT + 5) #define SET_MTU (GNB_OPT_INIT + 6) #define SET_CRYPTO_TYPE (GNB_OPT_INIT + 7) #define SET_CRYPTO_KEY_UPDATE_INTERVAL (GNB_OPT_INIT + 8) #define SET_MULTI_INDEX_TYPE (GNB_OPT_INIT + 9) #define SET_MULTI_FORWARD_TYPE (GNB_OPT_INIT + 10) #define SET_MULTI_SOCKET (GNB_OPT_INIT + 11) #define SET_SOCKET_IF_NAME (GNB_OPT_INIT + 12) #define SET_NODE_WORKER_QUEUE (GNB_OPT_INIT + 13) #define SET_INDEX_WORKER_QUEUE (GNB_OPT_INIT + 14) #define SET_INDEX_SERVICE_WORKER_QUEUE (GNB_OPT_INIT + 15) #define SET_PACKET_FILTER_WORKER_QUEUE (GNB_OPT_INIT + 16) #define SET_PORT_DETECT (GNB_OPT_INIT + 17) #define SET_DETECT_INTERVAL (GNB_OPT_INIT + 18) #define SET_PID_FILE (GNB_OPT_INIT + 20) #define SET_NODE_CACHE_FILE (GNB_OPT_INIT + 21) #define SET_LOG_FILE_PATH (GNB_OPT_INIT + 22) #define SET_LOG_UDP6 (GNB_OPT_INIT + 23) #define SET_LOG_UDP4 (GNB_OPT_INIT + 24) #define SET_LOG_UDP_TYPE (GNB_OPT_INIT + 25) #define SET_CONSOLE_LOG_LEVEL (GNB_OPT_INIT + 26) #define SET_FILE_LOG_LEVEL (GNB_OPT_INIT + 27) #define SET_UDP_LOG_LEVEL (GNB_OPT_INIT + 28) #define SET_CORE_LOG_LEVEL (GNB_OPT_INIT + 29) #define SET_PF_LOG_LEVEL (GNB_OPT_INIT + 30) #define SET_MAIN_LOG_LEVEL (GNB_OPT_INIT + 31) #define SET_NODE_LOG_LEVEL (GNB_OPT_INIT + 32) #define SET_INDEX_LOG_LEVEL (GNB_OPT_INIT + 33) #define SET_INDEX_SERVICE_LOG_LEVEL (GNB_OPT_INIT + 34) #define SET_DETECT_LOG_LEVEL (GNB_OPT_INIT + 35) #define SET_IF_DUMP (GNB_OPT_INIT + 36) #define SET_PF_TRACE (GNB_OPT_INIT + 37) #define SET_PF_ROUTE (GNB_OPT_INIT + 38) #define SET_TUN (GNB_OPT_INIT + 40) #define SET_INDEX_WORKER (GNB_OPT_INIT + 41) #define SET_INDEX_SERVICE_WORKER (GNB_OPT_INIT + 42) #define SET_DETECT_WORKER (GNB_OPT_INIT + 43) #define SET_UR0 (GNB_OPT_INIT + 44) #define SET_UR1 (GNB_OPT_INIT + 45) #define SET_SYSTEMD_DAEMON (GNB_OPT_INIT + 46) #define SET_IF_DRV (GNB_OPT_INIT + 47) #define SET_PF_WORKER_NUM (GNB_OPT_INIT + 48) #define SET_ZIP (GNB_OPT_INIT + 49) #define SET_ZIP_LEVEL (GNB_OPT_INIT + 50) #define SET_MEMORY_SCALE (GNB_OPT_INIT + 51) #define SET_SAFE_INDEX (GNB_OPT_INIT + 52) gnb_arg_list_t *gnb_es_arg_list; int is_self_test = 0; int is_verbose = 0; int is_trace = 0; int is_extreme_nat_traversal = 0; gnb_conf_t* gnb_argv(int argc,char *argv[]){ gnb_conf_t *conf; uint16_t port_host; char *ctl_block_file = NULL; int ret; int num; conf = malloc( sizeof(gnb_conf_t) ); memset(conf,0,sizeof(gnb_conf_t)); memset(&gnb_conf_ext_lite,0,sizeof(gnb_conf_ext_lite_t)); gnb_es_arg_list = gnb_arg_list_init(32); char listen_sockaddress4_string[GNB_IP4_PORT_STRING_SIZE]; memset(listen_sockaddress4_string,0,GNB_IP4_PORT_STRING_SIZE); char listen_sockaddress6_string[GNB_IP6_PORT_STRING_SIZE]; memset(listen_sockaddress6_string,0,GNB_IP6_PORT_STRING_SIZE); conf->addr_secure = 1; conf->activate_tun = 1; conf->activate_node_worker = 1; conf->activate_index_worker = 1; conf->activate_index_service_worker = 1; conf->activate_detect_worker = 1; conf->pf_worker_num = 0; conf->direct_forwarding = 1; conf->standard_forwarding = 1; conf->unified_forwarding = GNB_UNIFIED_FORWARDING_AUTO; conf->universal_relay0 = 0; conf->universal_relay1 = 0; /* IPv4最小MTU=576bytes IPv6最小MTU=1280bytes 如果 MTU 小于 1280 将无法设置 ipv6 地址 ipv4 的MTU设为532是因为减掉 payload 的首部占用的字节 */ conf->mtu = 1280; conf->pf_bits |= GNB_PF_BITS_CRYPTO_XOR; conf->crypto_key_update_interval = GNB_CRYPTO_KEY_UPDATE_INTERVAL_NONE; conf->crypto_passcode[3] = 0xFF; conf->crypto_passcode[2] = 0xFC; conf->crypto_passcode[1] = 0xFF; conf->crypto_passcode[0] = 0xFE; conf->zip_level = 0; conf->memory = GNB_MEMORY_SCALE_TINY; conf->multi_index_type = GNB_MULTI_ADDRESS_TYPE_SIMPLE_LOAD_BALANCE; conf->multi_forward_type = GNB_MULTI_ADDRESS_TYPE_SIMPLE_LOAD_BALANCE; conf->if_dump = 0; conf->log_udp_type = GNB_LOG_UDP_TYPE_BINARY; conf->console_log_level = GNB_LOG_LEVEL_UNSET; conf->file_log_level = GNB_LOG_LEVEL_UNSET; conf->udp_log_level = GNB_LOG_LEVEL_UNSET; conf->core_log_level = GNB_LOG_LEVEL_UNSET; conf->pf_log_level = GNB_LOG_LEVEL_UNSET; conf->main_log_level = GNB_LOG_LEVEL_UNSET; conf->node_log_level = GNB_LOG_LEVEL_UNSET; conf->index_log_level = GNB_LOG_LEVEL_UNSET; conf->index_service_log_level = GNB_LOG_LEVEL_UNSET; conf->detect_log_level = GNB_LOG_LEVEL_UNSET; conf->udp_socket_type = GNB_ADDR_TYPE_IPV4 | GNB_ADDR_TYPE_IPV6; conf->pf_woker_in_queue_length = 0xFFF; conf->pf_woker_out_queue_length = 0xFFF; conf->node_woker_queue_length = 0xFFF; conf->index_woker_queue_length = 0xFFF; conf->index_service_woker_queue_length = 0xFFF; conf->udp6_socket_num = 1; conf->udp4_socket_num = 1; conf->port_detect_range = DETECT_PORT_RANGE; conf->port_detect_start = DETECT_PORT_START; conf->port_detect_end = DETECT_PORT_END; conf->address_detect_interval_usec = GNB_ADDRESS_DETECT_INTERVAL_USEC; conf->full_detect_interval_sec = GNB_FULL_DETECT_INTERVAL_SEC; conf->safe_index = 0; conf->daemon = 0; conf->systemd_daemon = 0; conf->if_drv = GNB_IF_DRV_TYPE_DEFAULT; #if defined(__FreeBSD__) snprintf(conf->ifname,NAME_MAX,"%s","tun0"); #endif #if defined(__APPLE__) snprintf(conf->ifname,NAME_MAX,"%s","utun1"); #endif #if defined(__OpenBSD__) snprintf(conf->ifname,NAME_MAX,"%s","tun0"); #endif #if defined(__linux__) snprintf(conf->ifname,NAME_MAX,"%s","gnb_tun"); #endif #if defined(_WIN32) snprintf(conf->ifname,NAME_MAX,"%s","gnb_tun"); conf->if_drv = GNB_IF_DRV_TYPE_TAP_WINDOWS; #endif char *binary_dir; binary_dir = gnb_get_file_dir(argv[0], conf->binary_dir); if ( NULL==binary_dir ) { //这种情况几乎不会发生 #ifdef __UNIX_LIKE_OS__ snprintf(conf->binary_dir, PATH_MAX, "%s", "/tmp"); #endif #ifdef _WIN32 snprintf(conf->binary_dir, PATH_MAX+NAME_MAX, "%s", "c:\\"); #endif } #ifdef __UNIX_LIKE_OS__ char gnb_es_bin_path[PATH_MAX+NAME_MAX]; snprintf(gnb_es_bin_path, PATH_MAX+NAME_MAX, "%s/gnb_es", conf->binary_dir); gnb_arg_append(gnb_es_arg_list, gnb_es_bin_path); #endif #ifdef _WIN32 char gnb_es_bin_path_q[PATH_MAX+NAME_MAX]; snprintf(gnb_es_bin_path_q, PATH_MAX+NAME_MAX, "\"%s\\gnb_es.exe\"", conf->binary_dir); gnb_arg_append(gnb_es_arg_list, gnb_es_bin_path_q); #endif int flag; struct option long_options[] = { { "conf", required_argument, 0, 'c' }, { "nodeid", required_argument, 0, 'n' }, { "public-index-service", no_argument, 0, 'P' }, { "safe-index", no_argument, 0, SET_SAFE_INDEX }, { "index-address", required_argument, 0, 'I' }, { "node-address", required_argument, 0, 'a' }, { "node-route", required_argument, 0, 'r' }, { "ifname", required_argument, 0, 'i' }, { "if-drv", required_argument, 0, SET_IF_DRV }, { "mtu", required_argument, 0, SET_MTU }, { "crypto", required_argument, 0, SET_CRYPTO_TYPE }, { "passcode", required_argument, 0, 'p' }, { "crypto-key-update-interval", required_argument, 0, SET_CRYPTO_KEY_UPDATE_INTERVAL }, { "zip", required_argument, 0, SET_ZIP }, { "zip-level", required_argument, 0, SET_ZIP_LEVEL }, { "memory", required_argument, 0, SET_MEMORY_SCALE }, { "multi-index-type", required_argument, 0, SET_MULTI_INDEX_TYPE }, { "multi-forward-type", required_argument, 0, SET_MULTI_FORWARD_TYPE }, { "socket-if-name", required_argument, 0, SET_SOCKET_IF_NAME }, { "address-secure", required_argument, 0, SET_ADDR_SECURE }, { "listen", required_argument, 0, 'l' }, { "ctl-block", required_argument, 0, 'b' }, { "if-dump", required_argument, 0, SET_IF_DUMP }, { "ipv4-only", no_argument, 0, '4'}, { "ipv6-only", no_argument, 0, '6'}, { "extreme-nat-traversal", no_argument, 0, 'E' }, { "daemon", no_argument, 0, 'd' }, { "quiet", no_argument, 0, 'q' }, { "selftest", no_argument, 0, 't' }, { "verbose", no_argument, 0, 'V' }, { "trace", no_argument, 0, 'T' }, #if defined(__linux__) { "systemd", no_argument, 0, SET_SYSTEMD_DAEMON }, #endif { "es-argv", required_argument, 0, 'e' }, { "node-woker-queue", required_argument, 0, SET_NODE_WORKER_QUEUE }, { "index-woker-queue", required_argument, 0, SET_INDEX_WORKER_QUEUE }, { "index-woker-service-queue", required_argument, 0, SET_INDEX_SERVICE_WORKER_QUEUE }, { "packet-filter-woker-queue", required_argument, 0, SET_PACKET_FILTER_WORKER_QUEUE }, { "port-detect", required_argument, 0, SET_PORT_DETECT }, { "detect-interval", required_argument, 0, SET_DETECT_INTERVAL }, { "set-tun", required_argument, 0, SET_TUN }, { "index-worker", required_argument, 0, SET_INDEX_WORKER }, { "index-service-worker", required_argument, 0, SET_INDEX_SERVICE_WORKER }, { "node-detect-worker", required_argument, 0, SET_DETECT_WORKER }, { "pf-worker", required_argument, 0, SET_PF_WORKER_NUM }, { "multi-socket", required_argument, 0, SET_MULTI_SOCKET }, { "ur0", required_argument, 0, SET_UR0 }, { "ur1", required_argument, 0, SET_UR1 }, { "pf-route", required_argument, 0, SET_PF_ROUTE }, { "unified-forwarding", required_argument, 0, 'U' }, { "standard-forwarding", required_argument, 0, SET_STANDARD_FORWARDING}, { "direct-forwarding", required_argument, 0, SET_DIRECT_FORWARDING }, { "pid-file", required_argument, 0, SET_PID_FILE }, { "node-cache-file", required_argument, 0, SET_NODE_CACHE_FILE }, { "log-file-path", required_argument, 0, SET_LOG_FILE_PATH }, { "log-udp6", optional_argument, &flag, SET_LOG_UDP6 }, { "log-udp4", optional_argument, &flag, SET_LOG_UDP4 }, { "log-udp-type", required_argument, 0, SET_LOG_UDP_TYPE }, { "console-log-level", required_argument, 0, SET_CONSOLE_LOG_LEVEL }, { "file-log-level", required_argument, 0, SET_FILE_LOG_LEVEL }, { "udp-log-level", required_argument, 0, SET_UDP_LOG_LEVEL }, { "core-log-level", required_argument, 0, SET_CORE_LOG_LEVEL }, { "pf-log-level", required_argument, 0, SET_PF_LOG_LEVEL }, { "main-log-level", required_argument, 0, SET_MAIN_LOG_LEVEL }, { "node-log-level", required_argument, 0, SET_NODE_LOG_LEVEL }, { "index-log-level", required_argument, 0, SET_INDEX_LOG_LEVEL }, { "index-service-log-level", required_argument, 0, SET_INDEX_SERVICE_LOG_LEVEL }, { "node-detect-log-level", required_argument, 0, SET_DETECT_LOG_LEVEL }, { "help", no_argument, 0, 'h' }, { 0, 0, 0, 0 } }; int opt; int option_index = 0; while (1) { opt = getopt_long(argc, argv, "c:n:a:r:PI:b:l:i:46Edp:e:tqVTh",long_options, &option_index); if ( -1 == opt ) { break; } switch (opt) { case 'c': snprintf(conf->conf_dir, PATH_MAX, "%s", optarg); break; case 'P': conf->public_index_service = 1; break; case 'I': gnb_conf_ext_lite.index_address_string = optarg; break; case 'a': gnb_conf_ext_lite.node_address_string = optarg; break; case 'r': gnb_conf_ext_lite.node_route_string = optarg; break; case 'n': conf->local_uuid = (gnb_uuid_t)strtoull(optarg, NULL, 10); conf->lite_mode = 1; break; case 'i': #if defined(__linux__) || defined(_WIN32) snprintf(conf->ifname, 16, "%s", optarg); conf->ifname[15] = '\0'; #endif break; case SET_IF_DRV: if ( !strncmp(optarg, "wintun", sizeof("wintun")-1) ) { conf->if_drv = GNB_IF_DRV_TYPE_TAP_WINTUN; } else if ( !strncmp(optarg, "tap-windows", sizeof("tap-windows")-1) ) { conf->if_drv = GNB_IF_DRV_TYPE_TAP_WINDOWS; } else { conf->if_drv = GNB_IF_DRV_TYPE_DEFAULT; } break; case 'l': ret = check_listen_string(optarg); if ( 0 == ret ) { port_host = (uint16_t)strtoul(optarg, NULL, 10); snprintf(listen_sockaddress6_string, GNB_IP6_PORT_STRING_SIZE, "[:::%d]", port_host); snprintf(listen_sockaddress4_string, GNB_IP4_PORT_STRING_SIZE, "0.0.0.0:%d", port_host); } else if ( 4 == ret ) { snprintf(listen_sockaddress4_string, GNB_IP4_PORT_STRING_SIZE, "%s", optarg); } else if( 6 == ret ) { snprintf(listen_sockaddress6_string, GNB_IP6_PORT_STRING_SIZE, "%s", optarg); } break; case 'b': ctl_block_file = optarg; break; case '4': conf->udp_socket_type = GNB_ADDR_TYPE_IPV4; break; case '6': conf->udp_socket_type = GNB_ADDR_TYPE_IPV6; break; case 'E': is_extreme_nat_traversal = 1; break; case 'd': conf->daemon = 1; break; case 'p': gnb_build_passcode(conf->crypto_passcode, optarg); break; case 'q': conf->quiet = 1; break; case 't': is_self_test = 1; break; case 'V': is_verbose = 1; break; case 'T': is_trace = 1; break; case SET_SAFE_INDEX: conf->safe_index = 1; case SET_SYSTEMD_DAEMON: conf->systemd_daemon = 1; break; case SET_NODE_WORKER_QUEUE: conf->node_woker_queue_length = (uint16_t)strtoul(optarg, NULL, 10); break; case SET_INDEX_WORKER_QUEUE: conf->index_woker_queue_length = (uint16_t)strtoul(optarg, NULL, 10); break; case SET_INDEX_SERVICE_WORKER_QUEUE: conf->index_service_woker_queue_length = (uint16_t)strtoul(optarg, NULL, 10); break; case SET_PORT_DETECT: num = sscanf(optarg, "%hu,%hu,%hu", &conf->port_detect_range, &conf->port_detect_start, &conf->port_detect_end); if ( 3 != num ) { conf->port_detect_range = DETECT_PORT_RANGE; conf->port_detect_start = DETECT_PORT_START; conf->port_detect_end = DETECT_PORT_END; } break; case SET_DETECT_INTERVAL: num = sscanf(optarg, "%u,%u", &conf->address_detect_interval_usec, &conf->full_detect_interval_sec); if ( 2 != num ) { conf->address_detect_interval_usec = GNB_ADDRESS_DETECT_INTERVAL_USEC; conf->full_detect_interval_sec = GNB_FULL_DETECT_INTERVAL_SEC; } break; case SET_MTU: conf->mtu = (unsigned int)strtoul(optarg, NULL, 10); break; case SET_LOG_FILE_PATH: snprintf(conf->log_path , PATH_MAX, "%s", optarg); break; case SET_LOG_UDP_TYPE: if ( !strncmp(optarg, "binary", 16) ) { conf->log_udp_type = GNB_LOG_UDP_TYPE_BINARY; } else { conf->log_udp_type = GNB_LOG_UDP_TYPE_TEXT; } break; case SET_CONSOLE_LOG_LEVEL: conf->console_log_level = (uint8_t)strtoul(optarg, NULL, 10); break; case SET_FILE_LOG_LEVEL: conf->file_log_level = (uint8_t)strtoul(optarg, NULL, 10); break; case SET_UDP_LOG_LEVEL: conf->udp_log_level = (uint8_t)strtoul(optarg, NULL, 10); break; case SET_CORE_LOG_LEVEL: conf->core_log_level = (uint8_t)strtoul(optarg, NULL, 10); break; case SET_PF_LOG_LEVEL: conf->pf_log_level = (uint8_t)strtoul(optarg, NULL, 10); break; case SET_MAIN_LOG_LEVEL: conf->main_log_level = (uint8_t)strtoul(optarg, NULL, 10); break; case SET_NODE_LOG_LEVEL: conf->node_log_level = (uint8_t)strtoul(optarg, NULL, 10); break; case SET_INDEX_LOG_LEVEL: conf->index_log_level = (uint8_t)strtoul(optarg, NULL, 10); break; case SET_INDEX_SERVICE_LOG_LEVEL: conf->index_service_log_level = (uint8_t)strtoul(optarg, NULL, 10); break; case SET_DETECT_LOG_LEVEL: conf->detect_log_level = (uint8_t)strtoul(optarg, NULL, 10); break; case SET_CRYPTO_TYPE: if ( !strncmp(optarg, "none", 16) ) { conf->pf_bits &= ~(GNB_PF_BITS_CRYPTO_XOR | GNB_PF_BITS_CRYPTO_ARC4); } else if ( !strncmp(optarg, "xor", 16) ) { conf->pf_bits |= GNB_PF_BITS_CRYPTO_XOR; } else if ( !strncmp(optarg, "arc4", 16) ) { conf->pf_bits &= ~(GNB_PF_BITS_CRYPTO_XOR); //先消除默认的 XOR bit conf->pf_bits |= GNB_PF_BITS_CRYPTO_ARC4; } else { conf->pf_bits |= GNB_PF_BITS_CRYPTO_XOR; } break; case SET_ZIP: if ( !strncmp(optarg, "auto", sizeof("auto")-1) ) { conf->zip = GNB_ZIP_AUTO; } else if ( !strncmp(optarg, "force", sizeof("force")-1) ) { conf->zip = GNB_ZIP_FORCE; } else { conf->zip = GNB_ZIP_AUTO; } break; case SET_ZIP_LEVEL: conf->zip_level = (int8_t)strtoul(optarg, NULL, 10); if ( conf->zip_level > 9 ) { conf->zip_level = 9; } if ( conf->zip_level < -1 ) { conf->zip_level = -1; } break; case SET_MEMORY_SCALE: if ( !strncmp(optarg, "tiny", 16) ) { conf->memory = GNB_MEMORY_SCALE_TINY; } else if ( !strncmp(optarg, "small", 16) ) { conf->memory = GNB_MEMORY_SCALE_SMALL; } else if ( !strncmp(optarg, "large", 16) ) { conf->memory = GNB_MEMORY_SCALE_LARGE; } else if ( !strncmp(optarg, "huge", 16) ) { conf->memory = GNB_MEMORY_SCALE_HUGE; } else { conf->memory = GNB_MEMORY_SCALE_TINY; } break; case SET_MULTI_INDEX_TYPE: if ( !strncmp(optarg, "simple-fault-tolerant", 16) ) { conf->multi_index_type = GNB_MULTI_ADDRESS_TYPE_SIMPLE_FAULT_TOLERANT; } else if ( !strncmp(optarg, "simple-load-balance", 16) ) { conf->multi_index_type = GNB_MULTI_ADDRESS_TYPE_SIMPLE_LOAD_BALANCE; } else if ( !strncmp(optarg, "full", 16) ) { conf->multi_index_type = GNB_MULTI_ADDRESS_TYPE_FULL; } else { conf->multi_index_type = GNB_MULTI_ADDRESS_TYPE_SIMPLE_LOAD_BALANCE; } break; case SET_MULTI_FORWARD_TYPE: if ( !strncmp(optarg, "simple-fault-tolerant", sizeof("simple-fault-tolerant")-1) ) { conf->multi_forward_type = GNB_MULTI_ADDRESS_TYPE_SIMPLE_FAULT_TOLERANT; } else if ( !strncmp(optarg, "simple-load-balance", sizeof("simple-load-balance")-1) ) { conf->multi_forward_type = GNB_MULTI_ADDRESS_TYPE_SIMPLE_LOAD_BALANCE; } else { conf->multi_forward_type = GNB_MULTI_ADDRESS_TYPE_SIMPLE_FAULT_TOLERANT; } break; case SET_CRYPTO_KEY_UPDATE_INTERVAL: if ( !strncmp(optarg, "hour", sizeof("hour")-1 ) ) { conf->crypto_key_update_interval = GNB_CRYPTO_KEY_UPDATE_INTERVAL_HOUR; } else if ( !strncmp(optarg, "minute", sizeof("minute")-1) ) { conf->crypto_key_update_interval = GNB_CRYPTO_KEY_UPDATE_INTERVAL_MINUTE; } else if ( !strncmp(optarg, "none", sizeof("none")-1) ) { conf->crypto_key_update_interval = GNB_CRYPTO_KEY_UPDATE_INTERVAL_NONE; } else { conf->crypto_key_update_interval = GNB_CRYPTO_KEY_UPDATE_INTERVAL_NONE; } break; case SET_MULTI_SOCKET: if ( !strncmp(optarg, "on", 2) ) { conf->multi_socket = 1; } else if ( !strncmp(optarg, "off", 3) ) { conf->multi_socket = 0; } else { conf->multi_socket = 0; } break; case SET_PF_ROUTE: snprintf(conf->pf_route, NAME_MAX, "%s", optarg); break; case SET_TUN: if ( !strncmp(optarg, "on", 2) ) { conf->activate_tun = 1; } else if ( !strncmp(optarg, "off", 3) ) { conf->activate_tun = 0; } else { conf->activate_tun = 1; } break; case SET_INDEX_WORKER: if ( !strncmp(optarg, "on", 2) ) { conf->activate_index_worker = 1; } else if ( !strncmp(optarg, "off", 3) ) { conf->activate_index_worker = 0; } else { conf->activate_index_worker = 1; } break; case SET_INDEX_SERVICE_WORKER: if ( !strncmp(optarg, "on", 2) ) { conf->activate_index_service_worker = 1; } else if ( !strncmp(optarg, "off", 3) ) { conf->activate_index_service_worker = 0; } else { conf->activate_index_service_worker = 1; } break; case SET_DETECT_WORKER: if ( !strncmp(optarg, "on", 2) ) { conf->activate_detect_worker = 1; } else if ( !strncmp(optarg, "off", 3) ) { conf->activate_detect_worker = 0; } else { conf->activate_detect_worker = 1; } break; case SET_PF_WORKER_NUM: conf->pf_worker_num = (unsigned int)strtoul(optarg, NULL, 10); break; case SET_UR0: if ( !strncmp(optarg, "on", 2) ) { conf->universal_relay0 = 1; } else if ( !strncmp(optarg, "off", 3) ) { conf->universal_relay0 = 0; } else { conf->universal_relay0 = 1; } break; case SET_UR1: if ( !strncmp(optarg, "on", 2) ) { conf->universal_relay1 = 1; } else if ( !strncmp(optarg, "off", 3) ) { conf->universal_relay1 = 0; } else { conf->universal_relay1 = 1; } break; case 'U': if ( !strncmp(optarg, "off", sizeof("off")-1) ) { conf->unified_forwarding = GNB_UNIFIED_FORWARDING_OFF; } else if ( !strncmp(optarg, "auto", sizeof("auto")-1) ) { conf->unified_forwarding = GNB_UNIFIED_FORWARDING_AUTO; } else if ( !strncmp(optarg, "force", sizeof("force")-1) ) { conf->unified_forwarding = GNB_UNIFIED_FORWARDING_FORCE; } else if ( !strncmp(optarg, "super", sizeof("super")-1) ) { conf->unified_forwarding = GNB_UNIFIED_FORWARDING_SUPER; }else if ( !strncmp(optarg, "hyper", sizeof("hyper")-1) ) { conf->unified_forwarding = GNB_UNIFIED_FORWARDING_HYPER; } else { conf->unified_forwarding = GNB_UNIFIED_FORWARDING_AUTO; } break; case SET_DIRECT_FORWARDING: if ( !strncmp(optarg, "on", 2) ) { conf->direct_forwarding = 1; } else if ( !strncmp(optarg, "off", 3) ) { conf->direct_forwarding = 0; } else { conf->direct_forwarding = 1; } break; case SET_ADDR_SECURE: if ( !strncmp(optarg, "on", 2) ) { conf->addr_secure = 1; } else if ( !strncmp(optarg, "off", 3) ) { conf->addr_secure = 0; } else { conf->addr_secure = 1; } break; case SET_IF_DUMP: if ( !strncmp(optarg, "on", 2) ) { conf->if_dump = 1; } else if ( !strncmp(optarg, "off", 3) ) { conf->if_dump = 0; } else { conf->if_dump = 0; } break; case SET_SOCKET_IF_NAME: snprintf(conf->socket_ifname, 16, "%s", optarg); break; case SET_PID_FILE: snprintf(conf->pid_file, PATH_MAX, "%s", optarg); break; case SET_NODE_CACHE_FILE: snprintf(conf->node_cache_file, PATH_MAX, "%s", optarg); break; case 'e': gnb_setup_es_argv(optarg); break; case 'h': show_useage(argc, argv); exit(0); break; default: break; } if ( 0 == opt ) { switch (flag) { case SET_LOG_UDP4: if ( NULL != optarg ) { snprintf(conf->log_udp_sockaddress4_string, GNB_IP4_PORT_STRING_SIZE, "%s", optarg); } else { snprintf(conf->log_udp_sockaddress4_string, GNB_IP4_PORT_STRING_SIZE, "%s", "127.0.0.1:8666"); } break; default: break; } continue; } } if ( is_extreme_nat_traversal ) { conf->multi_socket = 1; conf->activate_detect_worker = 1; conf->multi_index_type = GNB_MULTI_ADDRESS_TYPE_FULL; gnb_setup_es_argv("--upnp"); } if ( 0 != conf->systemd_daemon ) { conf->daemon = 0; } if ( 1 == conf->public_index_service ) { conf->activate_tun = 0; conf->activate_node_worker = 0; conf->activate_index_worker = 0; conf->activate_index_service_worker = 1; conf->activate_detect_worker = 0; conf->index_service_woker_queue_length = 0x7FF; } if ( conf->pf_worker_num > 128 ) { conf->pf_worker_num = 128; } if ( conf->pf_worker_num > 0 ) { conf->unified_forwarding = GNB_UNIFIED_FORWARDING_OFF; } gnb_addr_secure = conf->addr_secure; switch (conf->memory) { case GNB_MEMORY_SCALE_TINY: conf->payload_block_size = 1024*8; conf->max_heap_fragment = 1024*8; conf->index_service_lru_size = 1024*2; break; case GNB_MEMORY_SCALE_SMALL: conf->payload_block_size = 1024*16; conf->max_heap_fragment = 1024*16; conf->index_service_lru_size = 1024*4; break; case GNB_MEMORY_SCALE_LARGE: conf->payload_block_size = 1024*32; conf->max_heap_fragment = 1024*32; conf->index_service_lru_size = 1024*32; break; case GNB_MEMORY_SCALE_HUGE: conf->payload_block_size = 1024*64; conf->max_heap_fragment = 1024*64; conf->index_service_lru_size = 1024*64; break; default: conf->payload_block_size = 1024*8; conf->max_heap_fragment = 1024*8; conf->index_service_lru_size = 1024*2; break; } if ( 1 == conf->multi_socket ) { conf->udp6_socket_num = 1; conf->udp4_socket_num = 5; } if ( conf->node_woker_queue_length < GNB_WORKER_MIN_QUEUE ) { conf->node_woker_queue_length = GNB_WORKER_MIN_QUEUE; } if ( conf->node_woker_queue_length > GNB_WORKER_MAX_QUEUE ) { conf->node_woker_queue_length = GNB_WORKER_MAX_QUEUE; } if ( conf->index_woker_queue_length < GNB_WORKER_MIN_QUEUE ) { conf->index_woker_queue_length = GNB_WORKER_MIN_QUEUE; } if ( conf->index_woker_queue_length > GNB_WORKER_MAX_QUEUE ) { conf->index_woker_queue_length = GNB_WORKER_MAX_QUEUE; } if ( conf->index_service_woker_queue_length < GNB_WORKER_MIN_QUEUE ) { conf->index_service_woker_queue_length = GNB_WORKER_MIN_QUEUE; } if ( conf->index_service_woker_queue_length > GNB_WORKER_MAX_QUEUE ) { conf->index_service_woker_queue_length = GNB_WORKER_MAX_QUEUE; } if ( conf->pf_woker_in_queue_length < GNB_WORKER_MIN_QUEUE ) { conf->pf_woker_in_queue_length = GNB_WORKER_MIN_QUEUE; } if ( conf->pf_woker_in_queue_length > GNB_WORKER_MAX_QUEUE ) { conf->pf_woker_in_queue_length = GNB_WORKER_MAX_QUEUE; } conf->pf_woker_out_queue_length = conf->pf_woker_in_queue_length; if ( GNB_ADDR_TYPE_IPV6 == conf->udp_socket_type && conf->mtu < 1280 ) { conf->mtu = 1280; } if ( '\0' == conf->pf_route[0] ) { snprintf(conf->pf_route, NAME_MAX, "gnb_pf_route"); } if ( '\0' != listen_sockaddress6_string[0] ) { gnb_setup_listen_addr_port(conf->listen_address6_string, &conf->udp6_ports[0], listen_sockaddress6_string, AF_INET6); } else { strncpy(conf->listen_address6_string,"::", sizeof("::")-1); conf->udp6_ports[0] = 9001; } if ( '\0' != listen_sockaddress4_string[0] ) { gnb_setup_listen_addr_port(conf->listen_address4_string, &conf->udp4_ports[0], listen_sockaddress4_string, AF_INET); } else { strncpy(conf->listen_address4_string,"0.0.0.0", sizeof("0.0.0.0")-1); conf->udp4_ports[0] = 9001; } if ( '\0' == conf->conf_dir[0] ) { if ( 0 == conf->public_index_service && 0 == conf->lite_mode ) { show_useage(argc, argv); exit(0); } } if ( 0 == conf->lite_mode && 0==conf->public_index_service ) { if ( '\0' == conf->map_file[0] ) { snprintf(conf->map_file, PATH_MAX+NAME_MAX, "%s/%s", conf->conf_dir, "gnb.map"); } if ( '\0' == conf->pid_file[0] ) { snprintf(conf->pid_file, PATH_MAX+NAME_MAX,"%s/%s", conf->conf_dir, "gnb.pid"); } if ( '\0' == conf->node_cache_file[0] ) { snprintf(conf->node_cache_file, PATH_MAX+NAME_MAX,"%s/%s", conf->conf_dir, "node_cache.dump"); } } else { conf->conf_dir[0] = '\0'; #ifdef __UNIX_LIKE_OS__ snprintf(conf->pid_file, PATH_MAX+NAME_MAX, "/tmp/gnb.%d.pid", conf->udp4_ports[0]); snprintf(conf->map_file, PATH_MAX+NAME_MAX, "/tmp/gnb.%d.map", conf->udp4_ports[0]); snprintf(conf->node_cache_file, PATH_MAX+NAME_MAX, "/tmp/node_cache.%d.dump", conf->udp4_ports[0]); #endif #ifdef _WIN32 snprintf(conf->map_file, PATH_MAX+NAME_MAX, "%s/gnb.%d.map", conf->binary_dir, conf->udp4_ports[0]); snprintf(conf->pid_file, PATH_MAX+NAME_MAX, "%s/gnb.%d.pid", conf->binary_dir, conf->udp4_ports[0]); snprintf(conf->node_cache_file, PATH_MAX+NAME_MAX, "%s/node_cache.%d.dump", conf->binary_dir, conf->udp4_ports[0]); #endif } if ( NULL != ctl_block_file ) { snprintf(conf->map_file, PATH_MAX+NAME_MAX, "%s", ctl_block_file); } char resolved_path[PATH_MAX+NAME_MAX]; if ( '\0' != conf->conf_dir[0] && NULL != gnb_realpath(conf->conf_dir,resolved_path) ) { strncpy(conf->conf_dir, resolved_path, PATH_MAX); } if ( NULL != gnb_realpath(conf->map_file,resolved_path) ) { strncpy(conf->map_file, resolved_path, PATH_MAX); } if ( NULL != gnb_realpath(conf->pid_file,resolved_path) ) { strncpy(conf->pid_file, resolved_path, PATH_MAX); } if ( '\0' != conf->node_cache_file[0] && NULL != gnb_realpath(conf->node_cache_file,resolved_path) ) { strncpy(conf->node_cache_file, resolved_path, PATH_MAX); } #ifdef __UNIX_LIKE_OS__ gnb_arg_append(gnb_es_arg_list, "-b"); gnb_arg_append(gnb_es_arg_list, conf->map_file); #endif #ifdef _WIN32 char gnb_map_path_q[PATH_MAX+NAME_MAX]; snprintf(gnb_map_path_q, PATH_MAX+NAME_MAX, "\"%s\"", conf->map_file); gnb_arg_append(gnb_es_arg_list, "-b"); gnb_arg_append(gnb_es_arg_list, gnb_map_path_q); #endif gnb_arg_append(gnb_es_arg_list, "--if-loop"); if ( 1 == conf->lite_mode ) { gnb_arg_append(gnb_es_arg_list, "--upnp"); } return conf; } static void show_useage(int argc,char *argv[]){ show_description(); printf("Usage: %s [-i IFNAME] -c CONFIG_PATH [OPTION]\n", argv[0]); printf("Command Summary:\n"); printf(" -c, --conf config path\n"); printf(" -n, --nodeid nodeid\n"); printf(" -P, --public-index-service run as public index service\n"); printf(" -I, --index-address setup index address\n"); printf(" -a, --node-address setup node ip address\n"); printf(" -r, --node-route setup node route\n"); printf(" -i, --ifname TUN Device Name\n"); printf(" -4, --ipv4-only Use IPv4 Only\n"); printf(" -6, --ipv6-only Use IPv6 Only\n"); printf(" -E, --extreme-nat-traversal extreme nat traversal\n"); printf(" -d, --daemon daemon\n"); printf(" -q, --quiet disabled console output\n"); printf(" -t, --selftest self test\n"); printf(" -p, --passcode a hexadecimal string of 32-bit unsigned integer,use to strengthen safety default:0xFFFCFFFE\n"); printf(" -U, --unified-forwarding \"off\",\"force\",\"auto\",\"super\",\"hyper\" default:\"auto\"; cannot be used with --pf-worker\n"); printf(" -l, --listen listen address default:\"0.0.0.0:9001\"\n"); printf(" -b, --ctl-block ctl block mapper file\n"); printf(" -e, --es-argv pass-through gnb_es argv\n"); printf(" -V, --verbose verbose mode\n"); printf(" -T, --trace trace mode\n"); #if defined(__linux__) printf(" --systemd systemd daemon\n"); #endif printf(" --node-worker-queue node worker queue length\n"); printf(" --index-worker-queue index worker queue length\n"); printf(" --index-service-worker-queue index service worker queue length\n"); printf(" --packet-filter-worker-queue packet filter worker queue length\n"); printf(" --port-detect node address detect port range,start,end\n"); printf(" --detect-interval node address detect interval default %u,%u\n", GNB_ADDRESS_DETECT_INTERVAL_USEC,GNB_FULL_DETECT_INTERVAL_SEC); printf(" --mtu TUN Device MTU ipv4:532~1500,ipv6:1280~1500\n"); printf(" --crypto ip frame crypto \"xor\",\"arc4\",\"none\" default:\"xor\"\n"); printf(" --crypto-key-update-interval crypto key update interval, \"hour\",\"minute\",none default:\"none\"\n"); printf(" --multi-index-type \"simple-fault-tolerant\",\"simple-load-balance\",\"full\" default:\"simple-load-balance\"\n"); printf(" --zip \"auto\", \"force\" default:\"auto\"\n"); printf(" --zip-level \"0\": no compression \"1\": best speed,\"9\": best compression\n"); printf(" --multi-forward-type \"simple-fault-tolerant\",\"simple-load-balance\" default:\"simple-fault-tolerant\"\n"); #ifdef _WIN32 printf(" --if-drv interface driver \"tap-windows\",\"wintun\" default:\"tap-windows\"\n"); #endif #ifdef __UNIX_LIKE_OS__ printf(" --socket-if-name example: \"eth0\",\"eno1\", only for unix-like os\n"); #endif printf(" --address-secure hide part of ip address in logs \"on\",\"off\" default:\"on\"\n"); printf(" --if-dump dump the interface data frame \"on\",\"off\" default:\"off\"\n"); printf(" --pf-route packet filter route\n"); printf(" --safe-index \"on\",\"off\" default:\"off\"\n"); printf(" --multi-socket \"on\",\"off\" default:\"off\"\n"); printf(" --standard-forwarding \"on\",\"off\" default:\"on\"\n"); printf(" --direct-forwarding \"on\",\"off\" default:\"on\"\n"); printf(" --set-tun \"on\",\"off\" default:\"on\"\n"); printf(" --index-worker \"on\",\"off\" default:\"on\"\n"); printf(" --index-service-worker \"on\",\"off\" default:\"on\"\n"); printf(" --node-detect-worker \"on\",\"off\" default:\"on\"\n"); #ifdef __UNIX_LIKE_OS__ printf(" --pf-worker [0-128] number of the packet filter worker default:0; cannot be used with --unified-forwarding, only for unix-like os\n"); #endif printf(" --memory \"tiny\",\"small\",\"large\",\"huge\" default:\"tiny\"\n"); printf(" --ur0 universal relay type 0 \"on\",\"off\" default:\"off\"\n"); printf(" --ur1 universal relay type 1 \"on\",\"off\" default:\"off\"\n"); printf(" --pid-file pid file\n"); printf(" --node-cache-file node address cache file\n"); printf(" --log-file-path log file path\n"); printf(" --log-udp4 send log to the address ipv4 default:\"127.0.0.1:8666\"\n"); printf(" --log-udp-type log udp type \"binary\",\"text\" default:\"binary\"\n"); printf(" --console-log-level log console level 0-3\n"); printf(" --file-log-level log file level 0-3\n" ); printf(" --udp-log-level log udp level 0-3\n"); printf(" --core-log-level core log level 0-3\n"); printf(" --pf-log-level packet filter log level 0-3\n"); printf(" --main-log-level main log level 0-3\n"); printf(" --node-log-level node log level 0-3\n"); printf(" --index-log-level index log level 0-3\n"); printf(" --index-service-log-level index service log level 0-3\n"); printf(" --node-detect-log-level node detect log level 0-3\n"); printf(" --help\n"); printf("Example:\n"); printf(" %s -i gnbtun -c $node_conf_dir -e \"--upnp\"\n",argv[0]); printf(" %s -P\n",argv[0]); printf(" %s -P --console-log-level=3 --index-service-log-level=3\n",argv[0]); printf(" %s -n 1001 -I \"$public_index_ip/$port\" --multi-socket=on -p $passcode\n",argv[0]); printf(" %s -n 1002 -I \"$public_index_ip/$port\" --multi-socket=on -p $passcode\n",argv[0]); printf(" %s -n 1001 -a \"i/0/$public_index_ip/$port\" --multi-socket=on -p $passcode\n",argv[0]); printf(" %s -n 1002 -a \"i/0/$public_index_ip/$port\" --multi-socket=on -p $passcode\n",argv[0]); } void gnb_setup_es_argv(char *es_argv_string){ int num; size_t len; char argv_string0[1024]; char argv_string1[1024]; len = strlen(es_argv_string); if ( len >1024 ) { return; } num = sscanf(es_argv_string,"%256[^ ] %256s", argv_string0, argv_string1); if ( 1 == num ) { gnb_arg_append(gnb_es_arg_list, argv_string0); } else if ( 2 == num ) { gnb_arg_append(gnb_es_arg_list, argv_string0); gnb_arg_append(gnb_es_arg_list, argv_string1); } return; } opengnb-ver1.6.0.a/src/gnb_binary.c000077500000000000000000000102541500454252100171520ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 #include "gnb_binary.h" static const char *bin2hex_convtab_down_case = "0123456789abcdef"; static const char *bin2hex_convtab_up_case = "0123456789ABCDEF"; char *gnb_bin2hex_case_string(void *bin, size_t bin_size, char *hex_string, int letter_case) { int i; char *p; const char *convtab; if ( FE_BIN2HEX_LOWERCASE == letter_case ) { convtab = bin2hex_convtab_down_case; } else { convtab = bin2hex_convtab_up_case; } p = hex_string; for ( i=0; i>4 ]; *p++ = convtab[ *(unsigned char *)bin & 0xF ]; bin++; } hex_string[i*2]='\0'; return hex_string; } char *gnb_bin2hex_string(void *bin, size_t bin_size, char *hex_string) { int i; char *p; const char *convtab; convtab = bin2hex_convtab_down_case; p = hex_string; for ( i=0; i>4 ]; *p++ = convtab[ *(unsigned char *)bin & 0xF ]; bin++; } hex_string[i*2]='\0'; return hex_string; } char *gnb_bin2hex_case(void *bin, size_t bin_size, char *hex_string, int letter_case) { int i; char *p; const char *convtab; if ( FE_BIN2HEX_LOWERCASE == letter_case ) { convtab = bin2hex_convtab_down_case; } else { convtab = bin2hex_convtab_up_case; } p = hex_string; for ( i=0; i>4 ]; *p++ = convtab[ *(unsigned char *)bin & 0xF ]; bin++; } return hex_string; } char *gnb_bin2hex(void *bin, size_t bin_size, char *hex_string) { int i; char *p; const char *convtab; convtab = bin2hex_convtab_down_case; p = hex_string; for ( i=0; i>4 ]; *p++ = convtab[ *(unsigned char *)bin & 0xF ]; bin++; } return hex_string; } void *gnb_hex2bin(char *hex_string, void *bin, size_t bin_size){ char *p = (char *)bin; int h; int l; int i; for ( i = 0; i < bin_size; i++ ) { if ( !isxdigit(hex_string[i * 2]) || !isxdigit(hex_string[i * 2 + 1]) ) { return NULL; } if ( isdigit( hex_string[i * 2] ) ) { h = hex_string[i * 2] - '0'; } else { h = toupper(hex_string[i * 2]) - 'A' + 10; } if ( isdigit( hex_string[i * 2 + 1] ) ) { l = hex_string[i * 2 + 1] - '0'; } else { l = toupper(hex_string[i * 2 + 1]) - 'A' + 10; } ((char *)bin)[i] = h*16 + l; } return bin; } char * gnb_get_hex_string8(void *byte4,char *dest){ gnb_hex_string8_t hex_string8; gnb_bin2hex(byte4, 4, dest); dest[8] = '\0'; return dest; } char * gnb_get_hex_string16(void *byte8, char *dest){ gnb_bin2hex(byte8, 8, dest); dest[16] = '\0'; return dest; } char * gnb_get_hex_string32(void *byte16, char *dest){ gnb_bin2hex(byte16, 16, dest); dest[32] = '\0'; return dest; } char * gnb_get_hex_string64(void *byte32, char *dest){ gnb_bin2hex(byte32, 32, dest); dest[64] = '\0'; return dest; } char * gnb_get_hex_string128(void *byte64, char *dest){ gnb_bin2hex(byte64, 64, dest); dest[128] = '\0'; return dest; } char * gnb_get_hex_string256(void *byte128, char *dest){ gnb_bin2hex(byte128, 128, dest); dest[256] = '\0'; return dest; } opengnb-ver1.6.0.a/src/gnb_binary.h000077500000000000000000000057551500454252100171710ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 . */ #ifndef GNB_BINARY_H #define GNB_BINARY_H #include #define FE_BIN2HEX_LOWERCASE 0 #define FE_BIN2HEX_CAPITALS 1 char *gnb_bin2hex_case_string(void *bin, size_t bin_size, char *hex_string, int letter_case); char *gnb_bin2hex_string(void *bin, size_t bin_size, char *hex_string); char *gnb_bin2hex_case(void *bin, size_t bin_size, char *hex_string, int letter_case); char *gnb_bin2hex(void *bin, size_t bin_size, char *hex_string); void *gnb_hex2bin(char *hex_string, void *bin, size_t bin_size); typedef struct _gnb_hex_string8_t{ char value[8+1]; }gnb_hex_string8_t; typedef struct _gnb_hex_string16_t{ char value[16+1]; }gnb_hex_string16_t; typedef struct _gnb_hex_string32_t{ char value[32+1]; }gnb_hex_string32_t; typedef struct _gnb_hex_string64_t{ char value[64+1]; }gnb_hex_string64_t; typedef struct _gnb_hex_string128_t{ char value[128+1]; }gnb_hex_string128_t; typedef struct _gnb_hex_string256_t{ char value[256+1]; }gnb_hex_string256_t; char * gnb_get_hex_string8(void *byte4, char *dest); char * gnb_get_hex_string16(void *byte8, char *dest); char * gnb_get_hex_string32(void *byte16, char *dest); char * gnb_get_hex_string64(void *byte32, char *dest); char * gnb_get_hex_string128(void *byte64, char *dest); char * gnb_get_hex_string256(void *byte128, char *dest); static char gnb_hex1_string256[256+1]; static char gnb_hex2_string256[256+1]; #define GNB_HEX1_BYTE8(bytes) gnb_get_hex_string8(bytes, gnb_hex1_string256) #define GNB_HEX1_BYTE16(bytes) gnb_get_hex_string16(bytes, gnb_hex1_string256) #define GNB_HEX1_BYTE32(bytes) gnb_get_hex_string32(bytes, gnb_hex1_string256) #define GNB_HEX1_BYTE64(bytes) gnb_get_hex_string64(bytes, gnb_hex1_string256) #define GNB_HEX1_BYTE128(bytes) gnb_get_hex_string128(bytes, gnb_hex1_string256) #define GNB_HEX1_BYTE256(bytes) gnb_get_hex_string256(bytes, gnb_hex1_string256) #define GNB_HEX2_BYTE8(bytes) gnb_get_hex_string8(bytes, gnb_hex2_string256) #define GNB_HEX2_BYTE16(bytes) gnb_get_hex_string16(bytes, gnb_hex2_string256) #define GNB_HEX2_BYTE32(bytes) gnb_get_hex_string32(bytes, gnb_hex2_string256) #define GNB_HEX2_BYTE64(bytes) gnb_get_hex_string64(bytes, gnb_hex2_string256) #define GNB_HEX2_BYTE128(bytes) gnb_get_hex_string128(bytes, gnb_hex2_string256) #define GNB_HEX2_BYTE256(bytes) gnb_get_hex_string256(bytes, gnb_hex2_string256) #endif opengnb-ver1.6.0.a/src/gnb_block.h000077500000000000000000000015771500454252100167750ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 . */ #ifndef GNB_BLOCK_H #define GNB_BLOCK_H #include typedef struct _gnb_block32_t { uint32_t size; unsigned char data[0]; }gnb_block32_t; #define GNB_BLOCK_VOID(block) *(void **)&block->data #endif opengnb-ver1.6.0.a/src/gnb_conf.c000077500000000000000000000063251500454252100166170ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 #include #include #include "gnb_conf_type.h" #include "gnb.h" char * check_domain_name(char *host_string){ if ( NULL != strchr(host_string, ':') ) { return NULL; } int i; for( i=0; i= 'a' && host_string[i] <= 'z' ) { return host_string; } } return NULL; } /*判断 配置行第二列是ip地址 还是node id*/ char * check_node_route(char *config_line_string){ if ( NULL != strchr(config_line_string, ':') || NULL != strchr(config_line_string, '.') ) { return NULL; } return config_line_string; } int gnb_test_field_separator(char *config_string){ int i; for ( i=0; i. */ #include #include #ifdef __UNIX_LIKE_OS__ #include #endif #ifdef _WIN32 #undef _WIN32_WINNT #define _WIN32_WINNT 0x0600 #include #include #endif #include "gnb_conf_file.h" #include "gnb_node.h" #include "gnb_keys.h" #include "gnb_udp.h" #include "ed25519/ed25519.h" #include "ed25519/sha512.h" char * check_domain_name(char *host_string); char * check_node_route(char *config_line_string); gnb_node_t * gnb_node_init(gnb_core_t *gnb_core, gnb_uuid_t uuid64); int check_listen_string(char *listen_string); void gnb_setup_listen_addr_port(char *listen_address6_string, uint16_t *port_ptr, char *sockaddress_string, int addr_type); void gnb_setup_es_argv(char *es_argv_string); int gnb_test_field_separator(char *config_string); static void address_file_config(gnb_core_t *gnb_core){ int ret; FILE *file; gnb_node_t *node; gnb_address_t address_st; gnb_address_list_t *static_address_list; gnb_address_list_t *dynamic_address_list; gnb_address_list_t *resolv_address_list; gnb_address_list_t *push_address_list; char idx_addr_file[PATH_MAX+NAME_MAX]; int num; snprintf(idx_addr_file, PATH_MAX+NAME_MAX, "%s/%s", gnb_core->conf->conf_dir, "address.conf"); file = fopen(idx_addr_file,"r"); if ( NULL == file ) { return; } char line_buffer[1024+1]; char attrib_string[16+1]; gnb_uuid_t uuid64; char host_string[INET6_ADDRSTRLEN+1]; uint16_t port = 0; int i = 0; i = 0; do{ num = fscanf(file,"%1024s\n",line_buffer); if ( EOF == num ) { break; } if ( '#' == line_buffer[0] ) { continue; } ret = gnb_test_field_separator(line_buffer); if ( GNB_CONF_FIELD_SEPARATOR_TYPE_SLASH == ret ) { num = sscanf(line_buffer,"%16[^/]/%llu/%46[^/]/%hu\n", attrib_string, &uuid64, host_string, &port); } else if ( GNB_CONF_FIELD_SEPARATOR_TYPE_VERTICAL == ret ) { num = sscanf(line_buffer,"%16[^|]|%llu|%46[^|]|%hu\n", attrib_string, &uuid64, host_string, &port); } else { num = 0; } if ( 4 != num ) { continue; } if ( NULL!=check_domain_name(host_string) ) { //域名 continue; } memset(&address_st, 0, sizeof(gnb_address_t)); address_st.port = htons(port); if ( NULL != strchr(host_string, '.') ) { //ipv4 inet_pton(AF_INET, host_string, (struct in_addr *)&address_st.m_address4); address_st.type = AF_INET; } else if ( NULL != strchr(host_string, ':') ) { //ipv6 inet_pton(AF_INET6, host_string, (struct in_addr *)&address_st.m_address6); address_st.type = AF_INET6; } else { continue; } //加入到 index address list if ( NULL != strchr(attrib_string, 'i') && uuid64 != gnb_core->local_node->uuid64 ) { gnb_address_list_update(gnb_core->index_address_ring.address_list, &address_st); } if ( NULL != strchr(attrib_string, 'u') && uuid64 != gnb_core->local_node->uuid64 ) { gnb_address_list_update(gnb_core->fwdu0_address_ring.address_list, &address_st); } node = GNB_HASH32_UINT64_GET_PTR(gnb_core->uuid_node_map, uuid64); if ( NULL == node ) { continue; } static_address_list = (gnb_address_list_t *)&node->static_address_block; dynamic_address_list = (gnb_address_list_t *)&node->dynamic_address_block; resolv_address_list = (gnb_address_list_t *)&node->resolv_address_block; push_address_list = (gnb_address_list_t *)&node->push_address_block; if ( AF_INET6 == address_st.type) { gnb_address_list_update(static_address_list, &address_st); node->udp_addr_status |= GNB_NODE_STATUS_IPV6_STATIC; node->udp_sockaddr6.sin6_family = AF_INET6; node->udp_sockaddr6.sin6_port = address_st.port; memcpy(&node->udp_sockaddr6.sin6_addr, address_st.m_address6, 16); } else if( AF_INET == address_st.type ) { gnb_address_list_update(static_address_list, &address_st); node->udp_addr_status |= GNB_NODE_STATUS_IPV4_STATIC; node->udp_sockaddr4.sin_family = AF_INET; node->udp_sockaddr4.sin_port = address_st.port; memcpy(&node->udp_sockaddr4.sin_addr, address_st.m_address4, 4); } if ( NULL != strchr(attrib_string, 'i') ) { node->type |= GNB_NODE_TYPE_IDX; if ( 0 != uuid64 && uuid64 != gnb_core->local_node->uuid64 ) { gnb_add_index_node_ring(gnb_core, uuid64); } } if ( NULL != strchr(attrib_string, 'r') ) { node->type |= GNB_NODE_TYPE_RELAY; } if ( NULL != strchr(attrib_string, 's') ) { node->type |= GNB_NODE_TYPE_SLIENCE; } if ( NULL != strchr(attrib_string, 'f') && uuid64 != gnb_core->local_node->uuid64 ) { node->type |= GNB_NODE_TYPE_FWD; gnb_add_forward_node_ring(gnb_core, uuid64); } }while(1); fclose(file); return; } static void load_node_cache(gnb_core_t *gnb_core){ int ret; FILE *file; gnb_node_t *node; gnb_address_t address_st; gnb_address_list_t *static_address_list; gnb_address_list_t *dynamic_address_list; gnb_address_list_t *resolv_address_list; gnb_address_list_t *push_address_list; int num; file = fopen(gnb_core->conf->node_cache_file,"r"); if (NULL==file) { return; } char line_buffer[1024+1]; char attrib_string[16+1]; gnb_uuid_t uuid64; char host_string[INET6_ADDRSTRLEN+1]; uint16_t port = 0; char key512_hex_string[128+1]; int i = 0; do{ num = fscanf(file,"%1024s\n",line_buffer); if ( EOF == num ) { break; } if ('#' == line_buffer[0]) { continue; } ret = gnb_test_field_separator(line_buffer); if ( GNB_CONF_FIELD_SEPARATOR_TYPE_SLASH == ret ) { num = sscanf(line_buffer,"%16[^/]/%llu/%46[^/]/%hu/%128s\n", attrib_string, &uuid64, host_string, &port, key512_hex_string); } else if ( GNB_CONF_FIELD_SEPARATOR_TYPE_VERTICAL == ret ) { num = sscanf(line_buffer,"%16[^|]|%llu|%46[^|]|%hu|%128s\n", attrib_string, &uuid64, host_string, &port, key512_hex_string); } else { num = 0; } if ( 5 != num ) { continue; } if ( 0 == port ) { continue; } memset(&address_st, 0, sizeof(gnb_address_t)); address_st.port = htons(port); if ( NULL != strchr(host_string, '.') ) { //ipv4 ret = inet_pton(AF_INET, host_string, &address_st.m_address4);\ if ( ret >0 ) { address_st.type = AF_INET; } else { address_st.type = AF_UNSPEC; } } else if ( NULL != strchr(host_string, ':') ) { //ipv6 ret = inet_pton(AF_INET6, host_string, &address_st.m_address6); if ( ret >0 ) { address_st.type = AF_INET6; } else { address_st.type = AF_UNSPEC; } } else { continue; } node = GNB_HASH32_UINT64_GET_PTR(gnb_core->uuid_node_map, uuid64); if ( NULL==node ) { continue; } push_address_list = (gnb_address_list_t *)&node->push_address_block; if ( AF_INET6 == address_st.type ) { gnb_address_list_update(push_address_list, &address_st); } else if ( AF_INET == address_st.type ) { gnb_address_list_update(push_address_list, &address_st); } }while(1); fclose(file); return; } void local_node_file_config(gnb_conf_t *conf){ FILE *file; char node_conf_file[PATH_MAX+NAME_MAX]; uint32_t log_level; uint32_t mtu; snprintf(node_conf_file, PATH_MAX+NAME_MAX,"%s/%s", conf->conf_dir, "node.conf"); file = fopen(node_conf_file,"r"); if ( NULL==file ) { printf("miss file [%s]\n", node_conf_file); exit(1); } char line_buffer[1024+1]; char field[256]; char value[256]; int value_int; char listen_sockaddress4_string[GNB_IP4_PORT_STRING_SIZE]; char listen_sockaddress6_string[GNB_IP6_PORT_STRING_SIZE]; uint16_t port_host = 0; int ret; int num; int listen6_idx = 0; int listen4_idx = 0; do{ num = fscanf(file,"%1024[^\n]\n",line_buffer); if ( EOF == num ) { break; } if ('#' == line_buffer[0]){ continue; } if ( !strncmp(line_buffer, "ifname", sizeof("ifname")-1) ) { num = sscanf(line_buffer, "%32[^ ] %16s", field, value); if ( 2 != num ) { printf("config ifname error in [%s]\n", node_conf_file); exit(1); } memset(conf->ifname, 0, 16); strncpy(conf->ifname,value, 16); conf->ifname[15] = '\0'; } if ( !strncmp(line_buffer, "if-drv", sizeof("if-drv")-1) ) { num = sscanf(line_buffer, "%32[^ ] %32s", field, value); if ( 2 != num ) { printf("config if-drv error in [%s]\n", node_conf_file); exit(1); } if ( !strncmp(value, "wintun", sizeof("wintun")-1) ) { conf->if_drv = GNB_IF_DRV_TYPE_TAP_WINTUN; } else if ( !strncmp(value, "tap-windows", sizeof("tap-windows")-1) ) { conf->if_drv = GNB_IF_DRV_TYPE_TAP_WINDOWS; } else { conf->if_drv = GNB_IF_DRV_TYPE_DEFAULT; } } if ( !strncmp(line_buffer, "nodeid", sizeof("nodeid")-1) ) { num = sscanf(line_buffer, "%32[^ ] %llu", field, &conf->local_uuid); if ( 2 != num ) { printf("config %s error in [%s]\n", "nodeid", node_conf_file); exit(1); } } if ( !strncmp(line_buffer, "listen", sizeof("listen")-1) ) { num = sscanf(line_buffer, "%128[^ ] %128s", field, value); if ( 2 != num ) { printf("config %s error in [%s]\n", "listen", node_conf_file); exit(1); } ret = check_listen_string(value); if ( 0 == ret ) { port_host = (uint16_t)strtoul(value, NULL, 10); snprintf(listen_sockaddress6_string, GNB_IP6_PORT_STRING_SIZE, "[:::%d]", port_host); snprintf(listen_sockaddress4_string, GNB_IP4_PORT_STRING_SIZE, "0.0.0.0:%d", port_host); if ( '[' != conf->listen_address6_string[0] ) { gnb_setup_listen_addr_port(conf->listen_address6_string, &conf->udp6_ports[listen6_idx], listen_sockaddress6_string, AF_INET6); } else { conf->udp6_ports[listen6_idx] = port_host; } if ( '\0' != conf->listen_address4_string[0] ) { gnb_setup_listen_addr_port(conf->listen_address4_string, &conf->udp4_ports[listen4_idx], listen_sockaddress4_string, AF_INET); } else { conf->udp4_ports[listen4_idx] = port_host; } listen6_idx++; listen4_idx++; } else if ( 6 == ret ) { strncpy(listen_sockaddress6_string, value, GNB_IP6_PORT_STRING_SIZE); listen_sockaddress6_string[GNB_IP6_PORT_STRING_SIZE-1] = '\0'; gnb_setup_listen_addr_port(conf->listen_address6_string, &conf->udp6_ports[listen6_idx], listen_sockaddress6_string, AF_INET6); listen6_idx++; } else if ( 4 == ret ) { strncpy(listen_sockaddress4_string, value, GNB_IP4_PORT_STRING_SIZE); listen_sockaddress4_string[GNB_IP4_PORT_STRING_SIZE-1] = '\0'; gnb_setup_listen_addr_port(conf->listen_address4_string, &conf->udp4_ports[listen4_idx], listen_sockaddress4_string, AF_INET); listen4_idx++; } } if ( !strncmp(line_buffer, "ctl-block", sizeof("ctl-block")-1) && 0 == conf->systemd_daemon ) { num = sscanf(line_buffer, "%32[^ ] %s", field, conf->map_file); if ( 2 != num ) { printf("config %s error in [%s]\n", "ctl-block", node_conf_file); exit(1); } } if ( !strncmp(line_buffer, "socket-if-name", sizeof("socket-if-name")-1) ) { num = sscanf(line_buffer, "%32[^ ] %s", field, conf->socket_ifname); if ( 2 != num ) { printf("config %s error in [%s]\n", "socket-if-name", node_conf_file); exit(1); } } if ( !strncmp(line_buffer, "pid-file", sizeof("pid-file")-1) && 0 == conf->systemd_daemon ) { num = sscanf(line_buffer, "%32[^ ] %s", field, conf->pid_file); if ( 2 != num ) { printf("config %s error in [%s]\n", "pid-file", node_conf_file); exit(1); } } if ( !strncmp(line_buffer, "es-argv", sizeof("es-argv")-1) ) { num = sscanf(line_buffer,"%32[^ ] %s", field, value); if ( 2 != num ) { printf("config %s error in [%s]\n", "es-argv", node_conf_file); exit(1); } gnb_setup_es_argv(value); } if ( !strncmp(line_buffer, "multi-socket", sizeof("multi-socket")-1) ) { num = sscanf(line_buffer, "%32[^ ] %4s", field, value); if ( 2 != num ) { printf("config %s error in [%s]\n", "multi-socket", node_conf_file); exit(1); } if ( !strncmp(value, "on", sizeof("on")-1) ) { conf->multi_socket = 1; } else { conf->multi_socket = 0; } } if ( !strncmp(line_buffer, "standard-forwarding", sizeof("standard-forwarding")-1) ) { num = sscanf(line_buffer,"%32[^ ] %4s", field, value); if ( 2 != num ) { printf("config %s error in [%s]\n", "standard-forwarding", node_conf_file); exit(1); } if ( !strncmp(value, "on", sizeof("on")-1) ) { conf->standard_forwarding = 1; } else { conf->standard_forwarding = 0; } } if ( !strncmp(line_buffer, "direct-forwarding", sizeof("direct-forwarding")-1) ) { num = sscanf(line_buffer,"%32[^ ] %4s", field, value); if ( 2 != num ) { printf("config %s error in [%s]\n", "direct-forwarding", node_conf_file); exit(1); } if ( !strncmp(value, "on", sizeof("on")-1) ) { conf->direct_forwarding = 1; } else { conf->direct_forwarding = 0; } } if ( !strncmp(line_buffer, "unified-forwarding", sizeof("unified-forwarding")-1) ) { num = sscanf(line_buffer,"%32[^ ] %10s", field, value); if ( 2 != num ) { printf("config %s error in [%s]\n", "unified-forwarding", node_conf_file); exit(1); } if ( !strncmp(value, "off", sizeof("off")-1) ) { conf->unified_forwarding = GNB_UNIFIED_FORWARDING_OFF; } else if ( !strncmp(value, "auto", sizeof("auto")-1) ) { conf->unified_forwarding = GNB_UNIFIED_FORWARDING_AUTO; } else if ( !strncmp(value, "force", sizeof("force")-1) ) { conf->unified_forwarding = GNB_UNIFIED_FORWARDING_FORCE; } else if ( !strncmp(value, "super", sizeof("super")-1) ) { conf->unified_forwarding = GNB_UNIFIED_FORWARDING_SUPER; } else if ( !strncmp(value, "hyper", sizeof("hyper")-1) ) { conf->unified_forwarding = GNB_UNIFIED_FORWARDING_HYPER; } else { conf->unified_forwarding = GNB_UNIFIED_FORWARDING_AUTO; } } if ( !strncmp(line_buffer, "ipv4-only", sizeof("ipv4-only")-1) ) { num = sscanf(line_buffer, "%32[^ ] %4s", field, value); if ( 2 != num ) { printf("config %s error in [%s]\n", "ipv4-only", node_conf_file); exit(1); } if ( !strncmp(value, "on", sizeof("on")-1) ) { conf->udp_socket_type = GNB_ADDR_TYPE_IPV4; } } if ( !strncmp(line_buffer, "ipv6-only", sizeof("ipv6-only")-1) ) { num = sscanf(line_buffer, "%32[^ ] %4s", field, value); if ( 2 != num ) { printf("config %s error in [%s]\n", "ipv6-only", node_conf_file); exit(1); } if ( !strncmp(value, "on", sizeof("on")-1) ) { conf->udp_socket_type = GNB_ADDR_TYPE_IPV6; } } if ( !strncmp(line_buffer, "passcode", sizeof("passcode")-1) ) { num = sscanf(line_buffer, "%32[^ ] %10s", field, value); if ( 2 != num ) { printf("config %s error in [%s]\n", "passcode", node_conf_file); exit(1); } gnb_build_passcode(conf->crypto_passcode, value); } if ( !strncmp(line_buffer, "quiet", sizeof("quiet")-1) ) { num = sscanf(line_buffer,"%32[^ ] %4s", field, value); if ( 2 != num ) { printf("config %s error in [%s]\n", "quiet", node_conf_file); exit(1); } if ( !strncmp(value, "on", sizeof("on")-1) ) { conf->quiet = 1; } else { conf->quiet = 0; } } if ( !strncmp(line_buffer, "daemon", sizeof("daemon")-1) ) { num = sscanf(line_buffer, "%32[^ ] %4s", field, value); if ( 2 != num ) { printf("config %s error in [%s]\n", "daemon", node_conf_file); exit(1); } if ( !strncmp(value, "on", sizeof("on")-1) && 0 == conf->systemd_daemon ) { conf->daemon = 1; } else { conf->daemon = 0; } } if ( !strncmp(line_buffer, "mtu", sizeof("mtu")-1) ) { num = sscanf(line_buffer, "%32[^ ] %d", field, &conf->mtu); if ( 2 != num ) { printf("config %s error in [%s]\n", "mtu", node_conf_file); exit(1); } } if ( !strncmp(line_buffer, "set-tun", sizeof("set-tun")-1) ) { num = sscanf(line_buffer, "%32[^ ] %4s", field, value); if ( 2 != num ) { printf("config %s error in [%s]\n", "set-tun", node_conf_file); exit(1); } if ( !strncmp(value, "on", sizeof("on")-1) ) { conf->activate_tun = 1; } else { conf->activate_tun = 0; } } if ( !strncmp(line_buffer, "address-secure", sizeof("address-secure")-1) ) { num = sscanf(line_buffer, "%32[^ ] %4s", field, value); if ( 2 != num ) { printf("config %s error in [%s]\n", "address-secure", node_conf_file); exit(1); } if ( !strncmp(value, "on", sizeof("on")-1) ) { conf->addr_secure = 1; } else { conf->addr_secure = 0; } gnb_addr_secure = conf->addr_secure; } if ( !strncmp(line_buffer, "node-worker", sizeof("node-worker")-1) ) { num = sscanf(line_buffer,"%32[^ ] %4s", field, value); if ( 2 != num ) { printf("config %s error in [%s]\n", "node-worker", node_conf_file); exit(1); } if ( !strncmp(value, "on", sizeof("on")-1) ) { conf->activate_node_worker = 1; } else { conf->activate_node_worker = 0; } } if ( !strncmp(line_buffer, "index-worker", sizeof("index-worker")-1) ) { num = sscanf(line_buffer, "%32[^ ] %4s", field, value); if ( 2 != num ) { printf("config %s error in [%s]\n", "index-worker", node_conf_file); exit(1); } if ( !strncmp(value, "on", sizeof("on")-1) ) { conf->activate_index_worker = 1; } else { conf->activate_index_worker = 0; } } if ( !strncmp(line_buffer, "index-service-worker", sizeof("index-service-worker")-1) ) { num = sscanf(line_buffer, "%32[^ ] %4s", field, value); if ( 2 != num ) { printf("config %s error in [%s]\n", "index-service-worker", node_conf_file); exit(1); } if ( !strncmp(value, "on", sizeof("on")-1) ) { conf->activate_index_service_worker = 1; } else { conf->activate_index_service_worker = 0; } } if ( !strncmp(line_buffer, "node-detect-worker", sizeof("node-detect-worker")-1) ) { num = sscanf(line_buffer, "%32[^ ] %4s", field, value); if ( 2 != num ) { printf("config %s error in [%s]\n", "node-detect-worker", node_conf_file); exit(1); } if ( !strncmp(value, "on", sizeof("on")-1) ) { conf->activate_detect_worker = 1; } else { conf->activate_detect_worker = 0; } } if ( !strncmp(line_buffer, "pf-worker", sizeof("pf-worker")-1) ) { num = sscanf(line_buffer, "%32[^ ] %hhd", field, &conf->pf_worker_num ); if ( 2 != num ) { printf("config %s error in [%s]\n", "pf-worker", node_conf_file); exit(1); } if ( conf->pf_worker_num > 128 ) { conf->pf_worker_num = 128; } } if ( !strncmp(line_buffer, "safe-index", sizeof("safe-index")-1) ) { num = sscanf(line_buffer, "%32[^ ] %4s", field, value); if ( 2 != num ) { printf("config %s error in [%s]\n", "safe-index", node_conf_file); exit(1); } if ( !strncmp(value, "on", sizeof("on")-1) ) { conf->safe_index = 1; } else { conf->safe_index = 0; } } if ( !strncmp(line_buffer, "port-detect", sizeof("port-detect")-1) ) { num = sscanf(line_buffer, "%32[^ ] %hu,%hu,%hu", field, &conf->port_detect_range, &conf->port_detect_start, &conf->port_detect_end); if ( 4 != num ) { printf("config %s error in [%s]\n", "port-detect", node_conf_file); exit(1); } } if ( !strncmp(line_buffer, "detect-interval", sizeof("detect-interval")-1) ) { num = sscanf(line_buffer, "%32[^ ] %u,%u", field, &conf->address_detect_interval_usec, &conf->full_detect_interval_sec); if ( 3 != num ) { printf("config %s error in [%s]\n", "detect-interval-usec", node_conf_file); exit(1); } } if ( !strncmp(line_buffer, "log-file-path", sizeof("log-file-path")-1) && 0 == conf->systemd_daemon ) { num = sscanf(line_buffer, "%32[^ ] %s", field, conf->log_path); if ( 2 != num ) { printf("config %s error in [%s]\n", "log-file-path", node_conf_file); exit(1); } } if ( !strncmp(line_buffer, "log-udp4", sizeof("log-udp4")-1) ) { num = sscanf(line_buffer, "%32[^ ] %s", field, conf->log_udp_sockaddress4_string); if ( 1 == num ) { snprintf(conf->log_udp_sockaddress4_string, 16 + 1 + sizeof("65535"), "%s", "127.0.0.1:9000"); } if ( 2 != num && 1 != num ) { printf("config %s error in [%s]\n", "log-udp4", node_conf_file); exit(1); } } if (!strncmp(line_buffer, "log-udp-type", sizeof("log-udp-type")-1) ) { num = sscanf(line_buffer, "%32[^ ] %2s", field, value); if ( 2 != num ) { printf("config %s error in [%s]\n", "log-udp-type", node_conf_file); exit(1); } if ( !strncmp(value, "binary", sizeof("binary")-1) ) { conf->log_udp_type = GNB_LOG_UDP_TYPE_BINARY; } else { conf->log_udp_type = GNB_LOG_UDP_TYPE_TEXT; } } if ( !strncmp(line_buffer, "console-log-level", sizeof("console-log-level")-1) ) { num = sscanf(line_buffer, "%32[^ ] %u", field, &log_level); if ( 2 != num ) { printf("config %s error in [%s]\n", "console-log-level", node_conf_file); exit(1); } conf->console_log_level = log_level; } if ( !strncmp(line_buffer, "file-log-level", sizeof("file-log-level")-1) ) { num = sscanf(line_buffer, "%32[^ ] %u", field, &log_level); if ( 2 != num ) { printf("config %s error in [%s]\n", "file-log-level", node_conf_file); exit(1); } conf->file_log_level = log_level; } if ( !strncmp(line_buffer, "udp-log-level", sizeof("udp-log-level")-1) ) { num = sscanf(line_buffer, "%32[^ ] %u", field, &log_level); if ( 2 != num ) { printf("config %s error in [%s]\n", "udp-log-level", node_conf_file); exit(1); } conf->udp_log_level = log_level; } if ( !strncmp(line_buffer, "core-log-level", sizeof("core-log-level")-1) ) { num = sscanf(line_buffer, "%32[^ ] %u", field, &log_level); if ( 2 != num ) { printf("config %s error in [%s]\n", "core-log-level", node_conf_file); exit(1); } conf->core_log_level = log_level; } if ( !strncmp(line_buffer, "pf-log-level", sizeof("pf-log-level")-1) ) { num = sscanf(line_buffer, "%32[^ ] %u", field, &log_level); if ( 2 != num ) { printf("config %s error in [%s]\n", "pf-log-level", node_conf_file); exit(1); } conf->pf_log_level = log_level; } if ( !strncmp(line_buffer, "main-log-level", sizeof("main-log-level")-1) ) { num = sscanf(line_buffer, "%32[^ ] %u", field, &log_level); if ( 2 != num ) { printf("config %s error in [%s]\n", "main-log-level", node_conf_file); exit(1); } conf->main_log_level = log_level; } if ( !strncmp(line_buffer, "node-log-level", sizeof("node-log-level")-1) ) { num = sscanf(line_buffer, "%32[^ ] %u", field, &log_level); if ( 2 != num ) { printf("config %s error in [%s]\n", "node-log-level", node_conf_file); exit(1); } conf->node_log_level = log_level; } if ( !strncmp(line_buffer, "index-log-level", sizeof("index-log-level")-1) ) { num = sscanf(line_buffer, "%32[^ ] %u", field, &log_level); if ( 2 != num ) { printf("config %s error in [%s]\n", "index-log-level", node_conf_file); exit(1); } conf->index_log_level = log_level; } if ( !strncmp(line_buffer, "index-service-log-level", sizeof("index-service-log-level")-1) ) { num = sscanf(line_buffer, "%32[^ ] %u", field, &log_level); if ( 2 != num ) { printf("config %s error in [%s]\n", "index-service-log-level", node_conf_file); exit(1); } conf->index_service_log_level = log_level; } if ( !strncmp(line_buffer, "node-detect-log-level", sizeof("node-detect-log-level")-1) ) { num = sscanf(line_buffer, "%32[^ ] %u", field, &log_level); if ( 2 != num ) { printf("config %s error in [%s]\n", "node-detect-log-level", node_conf_file); exit(1); } conf->detect_log_level = log_level; } if ( !strncmp(line_buffer, "log-file-path", sizeof("log-file-path")-1) ) { num = sscanf(line_buffer, "%32[^ ] %512s", field, conf->log_path); if ( 2 != num ) { printf("config %s error in [%s]\n", "log-file-path", node_conf_file); exit(1); } } if ( !strncmp(line_buffer, "pf-route", sizeof("pf-route")-1) ) { num = sscanf(line_buffer, "%32[^ ] %128s", field, conf->pf_route); if ( 2 != num ) { printf("config %s error in [%s]\n", "pf-route", node_conf_file); exit(1); } } if ( !strncmp(line_buffer, "crypto", sizeof("crypto")-1) ) { num = sscanf(line_buffer, "%32[^ ] %16s", field, value); if ( 2 != num ) { printf("config %s error in [%s]\n", "crypto", node_conf_file); exit(1); } if ( !strncmp(value, "none", 16) ) { conf->pf_bits &= ~(GNB_PF_BITS_CRYPTO_XOR | GNB_PF_BITS_CRYPTO_ARC4); } else if ( !strncmp(value, "xor", 16) ) { conf->pf_bits |= GNB_PF_BITS_CRYPTO_XOR; } else if ( !strncmp(value, "arc4", 16) ) { conf->pf_bits |= GNB_PF_BITS_CRYPTO_ARC4; } else { conf->pf_bits |= GNB_PF_BITS_CRYPTO_XOR; } } if (!strncmp(line_buffer, "zip", sizeof("zip")-1) ) { num = sscanf(line_buffer,"%32[^ ] %10s", field, value); if ( 2 != num ) { printf("config %s error in [%s]\n", "zip", node_conf_file); exit(1); } if ( !strncmp(value, "auto", sizeof("auto")-1) ) { conf->zip = GNB_ZIP_AUTO; } else if ( !strncmp(value, "force", sizeof("force")-1) ) { conf->zip = GNB_ZIP_FORCE; } else { conf->zip = GNB_ZIP_AUTO; } } if ( !strncmp(line_buffer, "zip-level", sizeof("zip-level")-1) ) { num = sscanf(line_buffer, "%32[^ ] %d", field, &value_int); if ( 2 != num ) { printf("config %s error in [%s]\n", "zip-level", node_conf_file); exit(1); } if ( value_int > 9 ) { value_int = 9; } if ( value_int < -1 ) { value_int = -1; } conf->zip_level = value_int; } if ( !strncmp(line_buffer, "memory", sizeof("memory")-1) ) { num = sscanf(line_buffer, "%32[^ ] %16s", field, value); if ( 2 != num ) { printf("config %s error in [%s]\n", "memory", node_conf_file); exit(1); } if ( !strncmp(value, "tiny", 16) ) { conf->memory = GNB_MEMORY_SCALE_TINY; } else if ( !strncmp(value, "small", 16) ) { conf->memory = GNB_MEMORY_SCALE_SMALL; } else if ( !strncmp(value, "large", 16) ) { conf->memory = GNB_MEMORY_SCALE_LARGE; } else if ( !strncmp(value, "huge", 16) ) { conf->memory = GNB_MEMORY_SCALE_HUGE; } else { conf->memory = GNB_MEMORY_SCALE_TINY; } } if ( !strncmp(line_buffer, "ur0", sizeof("ur0")-1) ) { num = sscanf(line_buffer, "%32[^ ] %4s", field, value); if ( 2 != num ) { printf("config %s error in [%s]\n", "ur0", node_conf_file); exit(1); } if ( !strncmp(value, "on", sizeof("on")-1) ) { conf->universal_relay0 = 1; } else { conf->universal_relay0 = 0; } } if ( !strncmp(line_buffer, "ur1", sizeof("ur1")-1) ) { num = sscanf(line_buffer, "%32[^ ] %4s", field, value); if ( 2 != num ) { printf("config %s error in [%s]\n", "ur1", node_conf_file); exit(1); } if ( !strncmp(value, "on", sizeof("on")-1) ) { conf->universal_relay1 = 1; } else { conf->universal_relay1 = 0; } } }while(1); fclose(file); if ( 1 == conf->multi_socket ) { conf->udp6_socket_num = 1; conf->udp4_socket_num = 5; } if ( 0 == conf->udp6_ports[ 0 ] ) { conf->udp6_ports[ 0 ] = 9001; } if ( 0 == conf->udp4_ports[ 0 ] ) { conf->udp4_ports[ 0 ] = 9001; } if ( conf->pf_worker_num > 0 ) { conf->unified_forwarding = GNB_UNIFIED_FORWARDING_OFF; } switch (conf->memory) { case GNB_MEMORY_SCALE_TINY: conf->payload_block_size = 1024*8; conf->max_heap_fragment = 1024*8; conf->index_service_lru_size = 1024*2; break; case GNB_MEMORY_SCALE_SMALL: conf->payload_block_size = 1024*16; conf->max_heap_fragment = 1024*16; conf->index_service_lru_size = 1024*4; break; case GNB_MEMORY_SCALE_LARGE: conf->payload_block_size = 1024*32; conf->max_heap_fragment = 1024*32; conf->index_service_lru_size = 1024*32; break; case GNB_MEMORY_SCALE_HUGE: conf->payload_block_size = 1024*64; conf->max_heap_fragment = 1024*64; conf->index_service_lru_size = 1024*64; break; default: conf->payload_block_size = 1024*8; conf->max_heap_fragment = 1024*8; conf->index_service_lru_size = 1024*2; break; } } size_t gnb_get_node_num_from_file(gnb_conf_t *conf){ size_t n = 0; FILE *file; gnb_uuid_t uuid64; char tun_ipv4_string[INET_ADDRSTRLEN+1]; char tun_netmask_string[INET_ADDRSTRLEN+1]; char route_file[PATH_MAX+NAME_MAX]; snprintf(route_file, PATH_MAX+NAME_MAX, "%s/%s", conf->conf_dir, "route.conf"); file = fopen(route_file,"r"); if ( NULL == file ) { printf("miss route.conf\n"); exit(1); } char line_buffer[1024+1]; int num; do{ num = fscanf(file,"%1024s\n",line_buffer); if ( EOF == num ) { break; } if ( '#' == line_buffer[0] ) { continue; } if ( NULL != check_node_route(line_buffer) ) { continue; } num = sscanf(line_buffer,"%llu|%16[^|]|%16[^|]", &uuid64, tun_ipv4_string, tun_netmask_string ); if ( 3 != num ) { continue; } n++; }while(1); fclose(file); return n; } static void load_route_config(gnb_core_t *gnb_core){ int ret; FILE *file; char route_file[PATH_MAX+NAME_MAX]; gnb_uuid_t uuid64; uint32_t tun_addr4; uint32_t tun_subnet_addr4; uint32_t tun_netmask_addr4; char tun_ipv4_string[INET_ADDRSTRLEN+1]; char tun_netmask_string[INET_ADDRSTRLEN+1]; char tun_ipv6_string[INET6_ADDRSTRLEN+1]; int num; gnb_node_t *node; snprintf(route_file, PATH_MAX+NAME_MAX, "%s/%s", gnb_core->conf->conf_dir, "route.conf"); file = fopen(route_file,"r"); if ( NULL == file ) { GNB_LOG1(gnb_core->log, GNB_LOG_ID_CORE, "miss route.conf\n"); exit(1); } char line_buffer[1024+1]; char netmask_class; gnb_core->node_nums = 0; do{ num = fscanf(file,"%1024s\n",line_buffer); if ( EOF == num ) { break; } if ( '#' == line_buffer[0] ) { continue; } if ( NULL != check_node_route(line_buffer) ) { continue; } ret = gnb_test_field_separator(line_buffer); if ( GNB_CONF_FIELD_SEPARATOR_TYPE_SLASH == ret ) { num = sscanf(line_buffer,"%llu/%16[^/]/%16[^/]", &uuid64, tun_ipv4_string, tun_netmask_string); } else if ( GNB_CONF_FIELD_SEPARATOR_TYPE_VERTICAL == ret ) { num = sscanf(line_buffer,"%llu|%16[^|]|%16[^|]", &uuid64, tun_ipv4_string, tun_netmask_string); } else { num = 0; } if ( 3 != num ) { continue; } node = GNB_HASH32_UINT64_GET_PTR(gnb_core->uuid_node_map, uuid64); if ( NULL==node ) { node = gnb_node_init(gnb_core, uuid64); GNB_HASH32_UINT64_SET(gnb_core->uuid_node_map, uuid64, node); gnb_core->node_nums++; } inet_pton(AF_INET, tun_ipv4_string, (struct in_addr *)&tun_addr4); inet_pton(AF_INET, tun_netmask_string, (struct in_addr *)&tun_netmask_addr4); tun_subnet_addr4 = tun_addr4 & tun_netmask_addr4; char *p = (char *)&tun_addr4; //根据ip地址最后一位判断是主机还是网络,如果是主机就作为 tun 的ip //tun_addr4 当前版本只能被设一次,今后可能会支持多个虚拟ip if ( 0 != p[3] && 0 == node->tun_addr4.s_addr ) { node->tun_addr4.s_addr = tun_addr4; node->tun_netmask_addr4.s_addr = tun_netmask_addr4; node->tun_subnet_addr4.s_addr = tun_subnet_addr4; snprintf(tun_ipv6_string, INET6_ADDRSTRLEN, "64:ff9b::%s", tun_ipv4_string); inet_pton(AF_INET6, tun_ipv6_string, (struct in6_addr *)&node->tun_ipv6_addr); GNB_HASH32_UINT32_SET(gnb_core->ipv4_node_map, node->tun_addr4.s_addr, node); } else { netmask_class = get_netmask_class(tun_netmask_addr4); if ( 'c' == netmask_class ) { GNB_HASH32_UINT32_SET(gnb_core->subnetc_node_map, tun_subnet_addr4, node); } if ( 'b' == netmask_class ) { GNB_HASH32_UINT32_SET(gnb_core->subnetb_node_map, tun_subnet_addr4, node); } if ( 'a' == netmask_class ) { GNB_HASH32_UINT32_SET(gnb_core->subneta_node_map, tun_subnet_addr4, node); } } }while(1); fclose(file); } static void set_node_route(gnb_core_t *gnb_core, gnb_uuid_t uuid64, char *relay_nodeids_string){ char *p; char *endptr; gnb_node_t *node; node = GNB_HASH32_UINT64_GET_PTR(gnb_core->uuid_node_map, uuid64); if ( NULL==node ) { return; } int line; for( line=0; lineroute_node[line][0] ) { break; } } if ( GNB_MAX_NODE_ROUTE == line ) { return; } gnb_uuid_t relay_nodeid; p = relay_nodeids_string; int row; for ( row = 0; row < GNB_MAX_NODE_RELAY; row++ ) { relay_nodeid = strtoull(p, &endptr, 10); if ( NULL == endptr ) { break; } if ( 0 == relay_nodeid ) { break; } node->route_node[line][row] = relay_nodeid; node->route_node_ttls[line]++; if ( '\0' == *endptr ) { break; } p = endptr; p++; } } static void set_node_route_mode(gnb_core_t *gnb_core, gnb_uuid_t uuid64, char *route_mode_string){ gnb_node_t *node; node = GNB_HASH32_UINT64_GET_PTR(gnb_core->uuid_node_map, uuid64); if ( NULL==node ) { return; } node->node_relay_mode = GNB_NODE_RELAY_DISABLE; if ( NULL != strstr(route_mode_string,"force") ) { node->node_relay_mode &= ~GNB_NODE_RELAY_AUTO; node->node_relay_mode |= GNB_NODE_RELAY_FORCE; } if ( NULL != strstr(route_mode_string,"auto") ) { node->node_relay_mode &= ~GNB_NODE_RELAY_FORCE; node->node_relay_mode |= GNB_NODE_RELAY_AUTO; } if ( NULL != strstr(route_mode_string,"balance") ) { node->node_relay_mode |= GNB_NODE_RELAY_BALANCE; } if ( NULL != strstr(route_mode_string,"static") ) { node->node_relay_mode |= GNB_NODE_RELAY_STATIC; } } static void load_route_node_config(gnb_core_t *gnb_core){ int ret; FILE *file; char route_file[PATH_MAX+NAME_MAX]; gnb_uuid_t uuid64; char row2_string[512+1]; gnb_conf_t *conf = gnb_core->conf; snprintf(route_file, PATH_MAX+NAME_MAX, "%s/%s", conf->conf_dir, "route.conf"); file = fopen(route_file,"r"); if ( NULL == file ) { printf("miss route.conf\n"); exit(1); } char line_buffer[1024+1]; int num; do{ num = fscanf(file,"%1024s\n",line_buffer); if ( EOF == num ) { break; } if ( '#' == line_buffer[0] ) { continue; } if ( NULL == check_node_route(line_buffer) ) { continue; } ret = gnb_test_field_separator(line_buffer); if ( GNB_CONF_FIELD_SEPARATOR_TYPE_SLASH == ret ) { num = sscanf(line_buffer,"%llu/%512s", &uuid64, row2_string); } else if ( GNB_CONF_FIELD_SEPARATOR_TYPE_VERTICAL == ret ) { num = sscanf(line_buffer,"%llu|%512s", &uuid64, row2_string); } else { num = 0; } if ( 2 != num ) { continue; } if ( row2_string[0] < '0' || row2_string[0] > '9' ) { set_node_route_mode(gnb_core, uuid64, row2_string); } else { set_node_route(gnb_core, uuid64, row2_string); } }while(1); fclose(file); } void gnb_config_safe(gnb_core_t *gnb_core){ //装载local node的公私钥 gnb_load_keypair(gnb_core); load_route_config(gnb_core); gnb_core->ctl_block->node_zone->node_num = gnb_core->node_nums; gnb_init_node_key512(gnb_core); gnb_core->local_node = GNB_HASH32_UINT64_GET_PTR(gnb_core->uuid_node_map, gnb_core->conf->local_uuid); if ( NULL==gnb_core->local_node ) { printf("miss local_node[%llu] is NULL\n", gnb_core->conf->local_uuid); exit(1); } gnb_core->local_node->udp_sockaddr6.sin6_port = htons(gnb_core->conf->udp6_ports[0]); gnb_core->local_node->udp_sockaddr4.sin_port = htons(gnb_core->conf->udp4_ports[0]); gnb_core->local_node->tun_sin_port4 = htons(gnb_core->conf->udp4_ports[0]); #if 0 //这里需要确保 tun_subnet_addr4 至少是一个C段,这样设定路由的时候,数据才会到 tun if( 0 == strncmp(gnb_core->local_node->tun_ipv4_netmask, "255.255.255.255", INET_ADDRSTRLEN) ) { snprintf(gnb_core->local_node->tun_ipv4_netmask,INET_ADDRSTRLEN,"%s", "255.255.255.0"); } #endif load_route_node_config(gnb_core); //加载 address.conf address_file_config(gnb_core); //加载 node_cache.dump if ( '\0' != gnb_core->conf->node_cache_file[0] ) { load_node_cache(gnb_core); } } opengnb-ver1.6.0.a/src/gnb_conf_file.h000077500000000000000000000016011500454252100176130ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 . */ #ifndef GNB_CONF_FILE_H #define GNB_CONF_FILE_H #include "gnb.h" void local_node_file_config(gnb_conf_t *conf); void gnb_config_safe(gnb_core_t *gnb_core); size_t gnb_get_node_num_from_file(gnb_conf_t *conf); #endif opengnb-ver1.6.0.a/src/gnb_conf_type.h000077500000000000000000000121461500454252100176630ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 . */ #ifndef GNB_CONF_TYPE_H #define GNB_CONF_TYPE_H #include #include #ifdef _WIN32 #ifndef NAME_MAX #define NAME_MAX 255 #endif #endif #include "gnb_node_type.h" #define GNB_PF_BITS_NONE (0x0) #define GNB_PF_BITS_CRYPTO_XOR (0x1) #define GNB_PF_BITS_CRYPTO_ARC4 (0x1 << 1) #define GNB_PF_BITS_ZIP (0x1 << 4) #define GNB_PF_BITS_7 (0x1 << 7) #define GNB_CRYPTO_KEY_UPDATE_INTERVAL_NONE 0x0 #define GNB_CRYPTO_KEY_UPDATE_INTERVAL_MINUTE 0x1 #define GNB_CRYPTO_KEY_UPDATE_INTERVAL_HOUR 0x2 #define GNB_MULTI_ADDRESS_TYPE_SIMPLE_FAULT_TOLERANT 0x1 #define GNB_MULTI_ADDRESS_TYPE_SIMPLE_LOAD_BALANCE 0x2 #define GNB_MULTI_ADDRESS_TYPE_FULL 0x3 #define GNB_WORKER_MIN_QUEUE 0xF #define GNB_WORKER_MAX_QUEUE 0x1FFF #define DETECT_PORT_START 1024 #define DETECT_PORT_END 65535 #define DETECT_PORT_RANGE 25 #define GNB_ADDRESS_DETECT_INTERVAL_USEC 5000 #define GNB_FULL_DETECT_INTERVAL_SEC 367 typedef struct _gnb_conf_t { char conf_dir[PATH_MAX]; uint8_t public_index_service; uint8_t safe_index; uint8_t lite_mode; gnb_uuid_t local_uuid; char binary_dir[PATH_MAX]; char map_file[PATH_MAX+NAME_MAX]; char pid_file[PATH_MAX+NAME_MAX]; char node_cache_file[PATH_MAX+NAME_MAX]; char log_path[PATH_MAX]; uint8_t console_log_level; uint8_t file_log_level; uint8_t udp_log_level; uint8_t core_log_level; uint8_t pf_log_level; uint8_t main_log_level; uint8_t node_log_level; uint8_t index_log_level; uint8_t index_service_log_level; uint8_t detect_log_level; uint8_t log_udp_type; char log_udp_sockaddress4_string[16 + 1 + sizeof("65535") + 1]; char ifname[256]; //根据 IFNAMSIZ 定义设为16 char socket_ifname[16]; int mtu; unsigned char pf_bits; unsigned char crypto_key_update_interval; unsigned char crypto_passcode[4]; #define GNB_ZIP_AUTO 0 #define GNB_ZIP_FORCE 1 int8_t zip; int8_t zip_level; // 0:Z_NO_COMPRESSION 9:Z_BEST_COMPRESSION -1 Z_DEFAULT_COMPRESSION #define GNB_MEMORY_SCALE_TINY (0x1) #define GNB_MEMORY_SCALE_SMALL (0x2) #define GNB_MEMORY_SCALE_LARGE (0x3) #define GNB_MEMORY_SCALE_HUGE (0x4) unsigned char memory; uint32_t index_service_lru_size; uint32_t payload_block_size; uint32_t max_heap_fragment; unsigned char multi_index_type; unsigned char multi_forward_type; unsigned char if_dump; unsigned char udp_socket_type; uint8_t multi_socket; char pf_route[NAME_MAX]; uint8_t pf_route_mode; #define GNB_UNIFIED_FORWARDING_OFF 0 #define GNB_UNIFIED_FORWARDING_FORCE 1 #define GNB_UNIFIED_FORWARDING_AUTO 2 #define GNB_UNIFIED_FORWARDING_SUPER 3 #define GNB_UNIFIED_FORWARDING_HYPER 4 uint8_t unified_forwarding; uint8_t direct_forwarding; uint8_t standard_forwarding; #define GNB_IF_DRV_TYPE_DEFAULT 0x0 #define GNB_IF_DRV_TYPE_TAP_WINDOWS 0xA #define GNB_IF_DRV_TYPE_TAP_WINTUN 0xB uint8_t if_drv; uint8_t activate_tun; uint8_t activate_node_worker; uint8_t activate_index_worker; uint8_t activate_index_service_worker; uint8_t activate_detect_worker; uint8_t pf_worker_num; uint8_t universal_relay0; uint8_t universal_relay1; char listen_address6_string[46 + 2 + 1 + sizeof("65535") + 1]; char listen_address4_string[16 + 1 + sizeof("65535") + 1]; #define GNB_MAX_UDP6_SOCKET_NUM 4 #define GNB_MAX_UDP4_SOCKET_NUM 16 //host 格式存放 uint16_t udp6_ports[GNB_MAX_UDP6_SOCKET_NUM]; uint16_t udp4_ports[GNB_MAX_UDP4_SOCKET_NUM]; //upnp 映射的端口,可由 upnp client 写入 uint16_t udp4_ext_ports[GNB_MAX_UDP4_SOCKET_NUM]; uint8_t udp6_socket_num; uint8_t udp4_socket_num; uint16_t pf_woker_in_queue_length; uint16_t pf_woker_out_queue_length; uint16_t node_woker_queue_length; uint16_t index_woker_queue_length; uint16_t index_service_woker_queue_length; uint16_t port_detect_range; uint16_t port_detect_start; uint16_t port_detect_end; uint32_t address_detect_interval_usec; uint32_t full_detect_interval_sec; uint8_t addr_secure; uint8_t daemon; uint8_t systemd_daemon; uint8_t quiet; }gnb_conf_t; typedef struct _gnb_conf_ext_lite_t { char *index_address_string; char *node_address_string; char *node_route_string; }gnb_conf_ext_lite_t; #define GNB_CONF_FIELD_SEPARATOR_TYPE_ERROR -1 #define GNB_CONF_FIELD_SEPARATOR_TYPE_SLASH 0 #define GNB_CONF_FIELD_SEPARATOR_TYPE_VERTICAL 1 #endif opengnb-ver1.6.0.a/src/gnb_config_lite.c000077500000000000000000000244211500454252100201510ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 "gnb_config_lite.h" #include "gnb_node.h" gnb_conf_ext_lite_t gnb_conf_ext_lite; char * check_domain_name(char *host_string); char * check_node_route(char *config_line_string); gnb_node_t * gnb_node_init(gnb_core_t *gnb_core, gnb_uuid_t uuid64); int gnb_test_field_separator(char *config_string); static char* gnb_string_pattern(char *in_buf, char delimiter, char *out_buf, size_t *out_buf_size){ char *p; p = in_buf; if ( *p == '\0' ) { p = NULL; return p; } size_t c = 0; do{ if ( delimiter == *p ) { p++; break; } if ( '\0' == *p ) { break; } if ( c == *out_buf_size ) { break; } *out_buf = *p; out_buf++; p++; c++; }while(*p); *out_buf = '\0'; *out_buf_size = c; return p; } static void setup_node_address(gnb_core_t *gnb_core, char *node_address_string) { int ret; char *p = node_address_string; char line_buffer[1024]; size_t line_buffer_size; gnb_node_t *node; gnb_address_t address_st; gnb_address_list_t *static_address_list; gnb_address_list_t *dynamic_address_list; gnb_address_list_t *resolv_address_list; gnb_address_list_t *push_address_list; int num; char attrib_string[16+1]; gnb_uuid_t uuid64; char host_string[INET6_ADDRSTRLEN+1]; uint16_t port = 0; int i = 0; i = 0; do{ line_buffer_size = 1024; p = gnb_string_pattern(p, ',', line_buffer, &line_buffer_size); if ( NULL == p ) { break; } ret = gnb_test_field_separator(line_buffer); if ( GNB_CONF_FIELD_SEPARATOR_TYPE_SLASH == ret ) { num = sscanf(line_buffer,"%16[^/]/%llu/%46[^/]/%hu\n", attrib_string, &uuid64, host_string, &port); } else if ( GNB_CONF_FIELD_SEPARATOR_TYPE_VERTICAL == ret ) { num = sscanf(line_buffer,"%16[^|]|%llu|%46[^|]|%hu\n", attrib_string, &uuid64, host_string, &port); } else { num = 0; } if ( 4 != num ) { continue; } if ( NULL!=check_domain_name(host_string) ) { //域名 continue; } memset(&address_st, 0, sizeof(gnb_address_t)); address_st.port = htons(port); if ( NULL != strchr(host_string, '.') ) { //ipv4 inet_pton(AF_INET, host_string, (struct in_addr *)&address_st.m_address4); address_st.type = AF_INET; } else if ( NULL != strchr(host_string, ':') ) { //ipv6 inet_pton(AF_INET6, host_string, (struct in_addr *)&address_st.m_address6); address_st.type = AF_INET6; } else { continue; } //加入到 index address list if ( NULL != strchr(attrib_string, 'i') && uuid64 != gnb_core->local_node->uuid64 ) { gnb_address_list_update(gnb_core->index_address_ring.address_list, &address_st); } if ( NULL != strchr(attrib_string, 'u') && uuid64 != gnb_core->local_node->uuid64 ) { gnb_address_list_update(gnb_core->fwdu0_address_ring.address_list, &address_st); } node = GNB_HASH32_UINT64_GET_PTR(gnb_core->uuid_node_map, uuid64); if ( NULL==node ) { continue; } static_address_list = (gnb_address_list_t *)&node->static_address_block; dynamic_address_list = (gnb_address_list_t *)&node->dynamic_address_block; resolv_address_list = (gnb_address_list_t *)&node->resolv_address_block; push_address_list = (gnb_address_list_t *)&node->push_address_block; if ( AF_INET6 == address_st.type ) { gnb_address_list_update(static_address_list, &address_st); node->udp_addr_status |= GNB_NODE_STATUS_IPV6_STATIC; node->udp_sockaddr6.sin6_family = AF_INET6; node->udp_sockaddr6.sin6_port = address_st.port; memcpy(&node->udp_sockaddr6.sin6_addr, address_st.m_address6, 16); } else if ( AF_INET == address_st.type ) { gnb_address_list_update(static_address_list, &address_st); node->udp_addr_status |= GNB_NODE_STATUS_IPV4_STATIC; node->udp_sockaddr4.sin_family = AF_INET; node->udp_sockaddr4.sin_port = address_st.port; memcpy(&node->udp_sockaddr4.sin_addr, address_st.m_address4, 4); } if ( NULL != strchr(attrib_string, 'i') ) { node->type |= GNB_NODE_TYPE_IDX; } if ( NULL != strchr(attrib_string, 'r') ) { node->type |= GNB_NODE_TYPE_RELAY; } if ( NULL != strchr(attrib_string, 's') ) { node->type |= GNB_NODE_TYPE_SLIENCE; } if ( NULL != strchr(attrib_string, 'f') && uuid64 != gnb_core->local_node->uuid64 ) { node->type |= GNB_NODE_TYPE_FWD; gnb_add_forward_node_ring(gnb_core, uuid64); } }while (p); } static void setup_node_route(gnb_core_t *gnb_core, char *node_route_string) { int ret; char *p = node_route_string; char line_buffer[1024+1]; size_t line_buffer_size; gnb_uuid_t uuid64; uint32_t tun_addr4; uint32_t tun_subnet_addr4; uint32_t tun_netmask_addr4; char tun_ipv4_string[INET_ADDRSTRLEN+1]; char tun_netmask_string[INET_ADDRSTRLEN+1]; char tun_ipv6_string[INET6_ADDRSTRLEN+1]; int num; gnb_node_t *node; char netmask_class; gnb_core->node_nums = 0; do{ line_buffer_size = 1024; p = gnb_string_pattern(p, ',', line_buffer, &line_buffer_size); if ( NULL == p ) { break; } if ( NULL != check_node_route(line_buffer) ) { continue; } ret = gnb_test_field_separator(line_buffer); if ( GNB_CONF_FIELD_SEPARATOR_TYPE_SLASH == ret ) { num = sscanf(line_buffer,"%llu/%16[^/]/%16[^/]", &uuid64, tun_ipv4_string, tun_netmask_string); } else if ( GNB_CONF_FIELD_SEPARATOR_TYPE_VERTICAL == ret ) { num = sscanf(line_buffer,"%llu|%16[^|]|%16[^|]", &uuid64, tun_ipv4_string, tun_netmask_string); } else { num = 0; } if ( 3 != num ) { continue; } node = GNB_HASH32_UINT64_GET_PTR(gnb_core->uuid_node_map, uuid64); if ( NULL==node ) { node = gnb_node_init(gnb_core, uuid64); GNB_HASH32_UINT64_SET(gnb_core->uuid_node_map, uuid64, node); gnb_core->node_nums++; } inet_pton(AF_INET, tun_ipv4_string, (struct in_addr *)&tun_addr4); inet_pton(AF_INET, tun_netmask_string, (struct in_addr *)&tun_netmask_addr4); tun_subnet_addr4 = tun_addr4 & tun_netmask_addr4; char *p = (char *)&tun_addr4; //根据ip地址最后一位判断是主机还是网络,如果是主机就作为 tun 的ip //tun_addr4 当前版本只能被设一次,今后可能会支持多个虚拟ip if ( 0 != p[3] && 0 == node->tun_addr4.s_addr ) { node->tun_addr4.s_addr = tun_addr4; node->tun_netmask_addr4.s_addr = tun_netmask_addr4; node->tun_subnet_addr4.s_addr = tun_subnet_addr4; snprintf(tun_ipv6_string, INET6_ADDRSTRLEN, "64:ff9b::%s", tun_ipv4_string); inet_pton(AF_INET6, tun_ipv6_string, (struct in6_addr *)&node->tun_ipv6_addr); GNB_HASH32_UINT32_SET(gnb_core->ipv4_node_map, node->tun_addr4.s_addr, node); } else { netmask_class = get_netmask_class(tun_netmask_addr4); if ( 'c' == netmask_class ) { GNB_HASH32_UINT32_SET(gnb_core->subnetc_node_map, tun_subnet_addr4, node); } if ( 'b' == netmask_class ) { GNB_HASH32_UINT32_SET(gnb_core->subnetb_node_map, tun_subnet_addr4, node); } if ( 'a' == netmask_class ) { GNB_HASH32_UINT32_SET(gnb_core->subneta_node_map, tun_subnet_addr4, node); } } }while(1); } void gnb_config_lite(gnb_core_t *gnb_core){ char index_node_address_string[1024]; int i; if ( NULL == gnb_conf_ext_lite.node_route_string ) { gnb_conf_ext_lite.node_route_string = "1001|10.1.0.1|255.255.0.0,1002|10.1.0.2|255.255.0.0,1003|10.1.0.3|255.255.0.0,1004|10.1.0.4|255.255.0.0,1005|10.1.0.5|255.255.0.0"; } setup_node_route(gnb_core, gnb_conf_ext_lite.node_route_string); gnb_core->ctl_block->node_zone->node_num = gnb_core->node_nums; gnb_core->ctl_block->core_zone->local_uuid = gnb_core->conf->local_uuid; gnb_init_node_key512(gnb_core); gnb_core->local_node = GNB_HASH32_UINT64_GET_PTR(gnb_core->uuid_node_map, gnb_core->conf->local_uuid); if ( NULL==gnb_core->local_node ) { printf("miss local_node[%llu] is NULL\n", gnb_core->conf->local_uuid); exit(1); } if ( NULL != gnb_conf_ext_lite.index_address_string ) { snprintf(index_node_address_string,1024,"i|0|%s", gnb_conf_ext_lite.index_address_string); for ( i=0; i < strlen(index_node_address_string); i++ ) { if ( '/' == index_node_address_string[i] ) { index_node_address_string[i] = '|'; } } setup_node_address(gnb_core, index_node_address_string); } if ( NULL != gnb_conf_ext_lite.node_address_string ) { setup_node_address(gnb_core, gnb_conf_ext_lite.node_address_string); } gnb_core->local_node->udp_sockaddr6.sin6_port = htons(gnb_core->conf->udp6_ports[0]); gnb_core->local_node->udp_sockaddr4.sin_port = htons(gnb_core->conf->udp4_ports[0]); gnb_core->local_node->tun_sin_port4 = htons(gnb_core->conf->udp4_ports[0]); } opengnb-ver1.6.0.a/src/gnb_config_lite.h000077500000000000000000000014311500454252100201520ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 . */ #ifndef GNB_CONF_LITE_H #define GNB_CONF_LITE_H #include "gnb.h" void gnb_config_lite(gnb_core_t *gnb_core); #endif opengnb-ver1.6.0.a/src/gnb_core.c000077500000000000000000001067571500454252100166340ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 #include #include #include "gnb.h" #ifdef __UNIX_LIKE_OS__ #include #include #include #include #include #endif #ifdef _WIN32 #include #include #endif #include #include "gnb_conf_file.h" #include "gnb_config_lite.h" #include "gnb_arg_list.h" #include "gnb_tun_drv.h" #include "gnb_exec.h" #include "gnb_binary.h" #include "gnb_payload16.h" #include "gnb_time.h" #include "gnb_keys.h" #include "gnb_mmap.h" #include "gnb_time.h" void gnb_set_env(const char *name, const char *value); void log_out_description(gnb_log_ctx_t *log); extern gnb_arg_list_t *gnb_es_arg_list; extern int is_verbose; extern int is_trace; static void gnb_setup_env(gnb_core_t *gnb_core){ char env_value_string[64]; gnb_set_env("GNB_IF_NAME", gnb_core->ifname); snprintf(env_value_string, 64, "%d", gnb_core->conf->mtu); gnb_set_env("GNB_MTU", env_value_string); gnb_set_env("GNB_TUN_IPV4", GNB_ADDR4STR1(&gnb_core->local_node->tun_addr4)); gnb_set_env("GNB_TUN_IPV6", GNB_ADDR6STR1(&gnb_core->local_node->tun_ipv6_addr)); } static void init_ctl_block(gnb_core_t *gnb_core, gnb_conf_t *conf){ gnb_mmap_block_t *mmap_block; void *memory; size_t node_num = 0; if ( 0 == conf->public_index_service && 0 == conf->lite_mode ) { //大致算出 node 的数量 node_num = gnb_get_node_num_from_file(conf); if ( 0==node_num ) { node_num = 256; } } else if ( 1 == conf->public_index_service && 0 == conf->lite_mode ) { node_num = 0; } else if ( 0 == conf->public_index_service && 1 == conf->lite_mode ) { node_num = 256; } else { node_num = 256; } /* (1 + conf->pf_worker_num) 是为 gnb_ctl_core_zone_t 中的 pf_worker_payload_blocks 预留 share memory 空间中 (primary_worker + pf_worker) 个 memmory block primary_worker 所使用的是 pf_worker_payload_blocks 第1块,后面的块由 pf_worker 依次占用 sizeof(gnb_block32_t) * 5 是 share memory 中ctl_block 有5个 zone 的 gnb_block32_t 结构占用的空间 */ size_t block_size = sizeof(uint32_t)*256 + sizeof(gnb_ctl_magic_number_t) + sizeof(gnb_ctl_conf_zone_t) + sizeof(gnb_ctl_core_zone_t) + (sizeof(gnb_payload16_t) + conf->payload_block_size + sizeof(gnb_payload16_t) + conf->payload_block_size) * (1 + conf->pf_worker_num) + sizeof(gnb_ctl_status_zone_t) + sizeof(gnb_ctl_node_zone_t) + sizeof(gnb_node_t)*node_num + sizeof(gnb_block32_t) * 5; unlink(conf->map_file); mmap_block = gnb_mmap_create(conf->map_file, block_size, GNB_MMAP_TYPE_READWRITE|GNB_MMAP_TYPE_CREATE); if ( NULL==mmap_block ) { printf("init_ctl_block error[%p] map_file=%s\n",mmap_block, conf->map_file); exit(1); } memory = gnb_mmap_get_block(mmap_block); gnb_core->ctl_block = gnb_ctl_block_build(memory, conf->payload_block_size, node_num, conf->pf_worker_num); gnb_core->ctl_block->mmap_block = mmap_block; } static void setup_log_ctx(gnb_conf_t *conf, gnb_log_ctx_t *log){ int rc; int pid; log->output_type = GNB_LOG_OUTPUT_STDOUT; if ( 0!=conf->daemon || 0!=conf->quiet ) { log->output_type = GNB_LOG_OUTPUT_NONE; } if ( '\0' != conf->log_path[0] ) { snprintf(log->log_file_path, PATH_MAX, "%s", conf->log_path); if ( 0 == conf->public_index_service ) { snprintf(log->log_file_name_std, PATH_MAX+NAME_MAX, "%s/std.log", conf->log_path); snprintf(log->log_file_name_debug, PATH_MAX+NAME_MAX, "%s/debug.log", conf->log_path); snprintf(log->log_file_name_error, PATH_MAX+NAME_MAX, "%s/error.log", conf->log_path); } else { snprintf(log->log_file_name_std, PATH_MAX+NAME_MAX, "%s/std.%d.log", conf->log_path, conf->udp4_ports[0]); snprintf(log->log_file_name_debug, PATH_MAX+NAME_MAX, "%s/debug.%d.log", conf->log_path, conf->udp4_ports[0]); snprintf(log->log_file_name_error, PATH_MAX+NAME_MAX, "%s/error.%d.log", conf->log_path, conf->udp4_ports[0]); } log->output_type |= GNB_LOG_OUTPUT_FILE; } else { log->log_file_path[0] = '\0'; } if ( GNB_LOG_LEVEL_UNSET == conf->console_log_level ) { if ( 0 == conf->lite_mode ) { conf->console_log_level = GNB_LOG_LEVEL1; } else { conf->console_log_level = GNB_LOG_LEVEL3; } } if ( GNB_LOG_LEVEL_UNSET == conf->file_log_level ) { if ( 0 == conf->lite_mode ) { conf->file_log_level = GNB_LOG_LEVEL1; } else { conf->file_log_level = GNB_LOG_LEVEL3; } } if ( GNB_LOG_LEVEL_UNSET == conf->udp_log_level ) { if ( 0 == conf->lite_mode ) { conf->udp_log_level = GNB_LOG_LEVEL1; } else { conf->udp_log_level = GNB_LOG_LEVEL3; } } if ( 1 == conf->lite_mode ) { if ( GNB_LOG_LEVEL_UNSET == conf->core_log_level ) { conf->core_log_level = GNB_LOG_LEVEL3; } if ( GNB_LOG_LEVEL_UNSET == conf->pf_log_level ) { conf->pf_log_level = GNB_LOG_LEVEL3; } if ( GNB_LOG_LEVEL_UNSET == conf->core_log_level ) { conf->core_log_level = GNB_LOG_LEVEL3; } if ( GNB_LOG_LEVEL_UNSET == conf->main_log_level ) { conf->main_log_level = GNB_LOG_LEVEL3; } if ( GNB_LOG_LEVEL_UNSET == conf->node_log_level ) { conf->node_log_level = GNB_LOG_LEVEL3; } if ( GNB_LOG_LEVEL_UNSET == conf->index_log_level ) { conf->index_log_level = GNB_LOG_LEVEL3; } if ( GNB_LOG_LEVEL_UNSET == conf->index_service_log_level ) { conf->index_service_log_level = GNB_LOG_LEVEL3; } } snprintf(log->config_table[GNB_LOG_ID_CORE].log_name, 20, "CORE"); log->config_table[GNB_LOG_ID_CORE].console_level = GNB_LOG_LEVEL1; log->config_table[GNB_LOG_ID_CORE].file_level = GNB_LOG_LEVEL1; log->config_table[GNB_LOG_ID_CORE].udp_level = GNB_LOG_LEVEL1; snprintf(log->config_table[GNB_LOG_ID_PF].log_name, 20, "PF"); log->config_table[GNB_LOG_ID_PF].console_level = GNB_LOG_LEVEL1; log->config_table[GNB_LOG_ID_PF].file_level = GNB_LOG_LEVEL1; log->config_table[GNB_LOG_ID_PF].udp_level = GNB_LOG_LEVEL1; snprintf(log->config_table[GNB_LOG_ID_MAIN_WORKER].log_name, 20, "MAIN"); log->config_table[GNB_LOG_ID_MAIN_WORKER].console_level = GNB_LOG_LEVEL1; log->config_table[GNB_LOG_ID_MAIN_WORKER].file_level = GNB_LOG_LEVEL1; log->config_table[GNB_LOG_ID_MAIN_WORKER].udp_level = GNB_LOG_LEVEL1; snprintf(log->config_table[GNB_LOG_ID_NODE_WORKER].log_name, 20, "NODE"); log->config_table[GNB_LOG_ID_NODE_WORKER].console_level = GNB_LOG_LEVEL1; log->config_table[GNB_LOG_ID_NODE_WORKER].file_level = GNB_LOG_LEVEL1; log->config_table[GNB_LOG_ID_NODE_WORKER].udp_level = GNB_LOG_LEVEL1; snprintf(log->config_table[GNB_LOG_ID_INDEX_WORKER].log_name, 20, "INDEX"); log->config_table[GNB_LOG_ID_INDEX_WORKER].console_level = GNB_LOG_LEVEL1; log->config_table[GNB_LOG_ID_INDEX_WORKER].file_level = GNB_LOG_LEVEL1; log->config_table[GNB_LOG_ID_INDEX_WORKER].udp_level = GNB_LOG_LEVEL1; snprintf(log->config_table[GNB_LOG_ID_INDEX_SERVICE_WORKER].log_name, 20, "INDEX_SERVICE"); log->config_table[GNB_LOG_ID_INDEX_SERVICE_WORKER].console_level = GNB_LOG_LEVEL1; log->config_table[GNB_LOG_ID_INDEX_SERVICE_WORKER].file_level = GNB_LOG_LEVEL1; log->config_table[GNB_LOG_ID_INDEX_SERVICE_WORKER].udp_level = GNB_LOG_LEVEL1; snprintf(log->config_table[GNB_LOG_ID_DETECT_WORKER].log_name, 20, "FULL_DETECT"); log->config_table[GNB_LOG_ID_DETECT_WORKER].console_level = GNB_LOG_LEVEL1; log->config_table[GNB_LOG_ID_DETECT_WORKER].file_level = GNB_LOG_LEVEL1; log->config_table[GNB_LOG_ID_DETECT_WORKER].udp_level = GNB_LOG_LEVEL1; if ( GNB_LOG_LEVEL_UNSET != conf->core_log_level ) { if ( 0 == conf->lite_mode ) { if ( conf->console_log_level >= conf->core_log_level ) { log->config_table[GNB_LOG_ID_CORE].console_level = conf->core_log_level; } if ( conf->file_log_level >= conf->core_log_level ) { log->config_table[GNB_LOG_ID_CORE].file_level = conf->core_log_level; } if ( conf->udp_log_level >= conf->core_log_level ) { log->config_table[GNB_LOG_ID_CORE].udp_level = conf->core_log_level; } } else { log->config_table[GNB_LOG_ID_CORE].console_level = GNB_LOG_LEVEL3; log->config_table[GNB_LOG_ID_CORE].file_level = GNB_LOG_LEVEL3; log->config_table[GNB_LOG_ID_CORE].udp_level = GNB_LOG_LEVEL3; } } if ( GNB_LOG_LEVEL_UNSET != conf->pf_log_level ) { if ( 0 == conf->lite_mode ) { if ( conf->pf_log_level >= log->config_table[GNB_LOG_ID_PF].console_level ) { log->config_table[GNB_LOG_ID_PF].console_level = conf->pf_log_level; } if ( conf->pf_log_level >= log->config_table[GNB_LOG_ID_PF].file_level ) { log->config_table[GNB_LOG_ID_PF].file_level = conf->pf_log_level; } if ( conf->pf_log_level >= log->config_table[GNB_LOG_ID_PF].udp_level ) { log->config_table[GNB_LOG_ID_PF].udp_level = conf->pf_log_level; } } else { log->config_table[GNB_LOG_ID_PF].console_level = GNB_LOG_LEVEL3; log->config_table[GNB_LOG_ID_PF].file_level = GNB_LOG_LEVEL3; log->config_table[GNB_LOG_ID_PF].udp_level = GNB_LOG_LEVEL3; } } if ( GNB_LOG_LEVEL_UNSET != conf->main_log_level ) { if ( 0 == conf->lite_mode ) { if ( conf->console_log_level >= conf->main_log_level ) { log->config_table[GNB_LOG_ID_MAIN_WORKER].console_level = conf->main_log_level; } if ( conf->file_log_level >= conf->main_log_level ) { log->config_table[GNB_LOG_ID_MAIN_WORKER].file_level = conf->main_log_level; } if ( conf->udp_log_level >= conf->main_log_level ) { log->config_table[GNB_LOG_ID_MAIN_WORKER].udp_level = conf->main_log_level; } } else { log->config_table[GNB_LOG_ID_MAIN_WORKER].console_level = GNB_LOG_LEVEL3; log->config_table[GNB_LOG_ID_MAIN_WORKER].file_level = GNB_LOG_LEVEL3; log->config_table[GNB_LOG_ID_MAIN_WORKER].udp_level = GNB_LOG_LEVEL3; } } if ( GNB_LOG_LEVEL_UNSET != conf->node_log_level ) { if ( 0 == conf->lite_mode ) { if ( conf->console_log_level >= conf->node_log_level ) { log->config_table[GNB_LOG_ID_NODE_WORKER].console_level = conf->node_log_level; } if ( conf->file_log_level >= conf->node_log_level ) { log->config_table[GNB_LOG_ID_NODE_WORKER].file_level = conf->node_log_level; } if ( conf->udp_log_level >= conf->node_log_level ) { log->config_table[GNB_LOG_ID_NODE_WORKER].udp_level = conf->node_log_level; } } else { log->config_table[GNB_LOG_ID_NODE_WORKER].console_level = GNB_LOG_LEVEL3; log->config_table[GNB_LOG_ID_NODE_WORKER].file_level = GNB_LOG_LEVEL3; log->config_table[GNB_LOG_ID_NODE_WORKER].udp_level = GNB_LOG_LEVEL3; } } if ( GNB_LOG_LEVEL_UNSET != conf->index_log_level ) { if ( 0 == conf->lite_mode ) { if ( conf->console_log_level >= conf->index_log_level ) { log->config_table[GNB_LOG_ID_INDEX_WORKER].console_level = conf->index_log_level; } if ( conf->file_log_level >= conf->index_log_level ) { log->config_table[GNB_LOG_ID_INDEX_WORKER].file_level = conf->index_log_level; } if ( conf->udp_log_level >= conf->index_log_level ) { log->config_table[GNB_LOG_ID_INDEX_WORKER].udp_level = conf->index_log_level; } } else { log->config_table[GNB_LOG_ID_INDEX_WORKER].console_level = GNB_LOG_LEVEL3; log->config_table[GNB_LOG_ID_INDEX_WORKER].file_level = GNB_LOG_LEVEL3; log->config_table[GNB_LOG_ID_INDEX_WORKER].udp_level = GNB_LOG_LEVEL3; } } if ( GNB_LOG_LEVEL_UNSET != conf->index_service_log_level ) { if ( 0 == conf->lite_mode ) { if ( conf->console_log_level >= conf->index_service_log_level ) { log->config_table[GNB_LOG_ID_INDEX_SERVICE_WORKER].console_level = conf->index_service_log_level; } if ( conf->file_log_level >= conf->index_service_log_level ) { log->config_table[GNB_LOG_ID_INDEX_SERVICE_WORKER].file_level = conf->index_service_log_level; } if ( conf->udp_log_level >= conf->index_service_log_level ) { log->config_table[GNB_LOG_ID_INDEX_SERVICE_WORKER].udp_level = conf->index_service_log_level; } } else { log->config_table[GNB_LOG_ID_INDEX_SERVICE_WORKER].console_level = GNB_LOG_LEVEL3; log->config_table[GNB_LOG_ID_INDEX_SERVICE_WORKER].file_level = GNB_LOG_LEVEL3; log->config_table[GNB_LOG_ID_INDEX_SERVICE_WORKER].udp_level = GNB_LOG_LEVEL3; } } if ( GNB_LOG_LEVEL_UNSET != conf->detect_log_level ) { if ( 0 == conf->lite_mode ) { if ( conf->console_log_level >= conf->detect_log_level ) { log->config_table[GNB_LOG_ID_DETECT_WORKER].console_level = conf->detect_log_level; } if ( conf->file_log_level >= conf->detect_log_level ) { log->config_table[GNB_LOG_ID_DETECT_WORKER].file_level = conf->detect_log_level; } if ( conf->udp_log_level >= conf->detect_log_level ) { log->config_table[GNB_LOG_ID_DETECT_WORKER].udp_level = conf->detect_log_level; } } else { log->config_table[GNB_LOG_ID_DETECT_WORKER].console_level = GNB_LOG_LEVEL3; log->config_table[GNB_LOG_ID_DETECT_WORKER].file_level = GNB_LOG_LEVEL3; log->config_table[GNB_LOG_ID_DETECT_WORKER].udp_level = GNB_LOG_LEVEL3; } } gnb_log_file_rotate(log); gnb_log_udp_open(log); log->log_udp_type = conf->log_udp_type; log->log_payload_type = GNB_PAYLOAD_TYPE_UDPLOG; if ( '\0' != conf->log_udp_sockaddress4_string[0] ) { rc = gnb_log_udp_set_addr4_string(log, conf->log_udp_sockaddress4_string); log->output_type |= GNB_LOG_OUTPUT_UDP; } return; } void update_node_crypto_key(gnb_core_t *gnb_core, uint64_t now_sec){ int need_update_time_seed; size_t num = gnb_core->ctl_block->node_zone->node_num; if ( 0 == num ) { return; } need_update_time_seed = gnb_verify_seed_time(gnb_core, now_sec); if ( 0 == need_update_time_seed ) { return; } gnb_update_time_seed(gnb_core, now_sec); int i; gnb_node_t *node; for ( i=0; ictl_block->node_zone->node[i]; if ( gnb_core->local_node->uuid64 == node->uuid64 ) { continue; } gnb_build_crypto_key(gnb_core, node); } } gnb_core_t* gnb_core_create(gnb_conf_t *conf){ gnb_core_t *gnb_core; gnb_heap_t *heap = gnb_heap_create(conf->max_heap_fragment); gnb_core = gnb_heap_alloc(heap, sizeof(gnb_core_t)); memset(gnb_core, 0, sizeof(gnb_core_t)); gnb_core->heap = heap; init_ctl_block(gnb_core, conf); gnb_core->conf = &gnb_core->ctl_block->conf_zone->conf_st; memcpy(gnb_core->conf, conf, sizeof(gnb_conf_t)); gnb_core->log = &gnb_core->ctl_block->core_zone->log_ctx_st; gnb_log_ctx_t *log = gnb_log_ctx_create(); memcpy(gnb_core->log, log, sizeof(gnb_log_ctx_t)); free(log); gnb_core->ed25519_private_key = gnb_core->ctl_block->core_zone->ed25519_private_key; gnb_core->ed25519_public_key = gnb_core->ctl_block->core_zone->ed25519_public_key; gnb_core->index_address_ring.address_list = (gnb_address_list_t *)gnb_core->ctl_block->core_zone->index_address_block; gnb_core->index_address_ring.address_list->num = 0; gnb_core->index_address_ring.address_list->size = GNB_MAX_ADDR_RING; gnb_core->fwdu0_address_ring.address_list = (gnb_address_list_t *)gnb_core->ctl_block->core_zone->ufwd_address_block; gnb_core->fwdu0_address_ring.address_list->num = 0; gnb_core->fwdu0_address_ring.address_list->size = 16; gnb_core->ifname = (char *)gnb_core->ctl_block->core_zone->ifname; gnb_core->if_device_string = (char *)gnb_core->ctl_block->core_zone->if_device_string; gnb_core->uuid_node_map = gnb_hash32_create(gnb_core->heap, 1024, 1024); //以节点的uuid64作为key的 node 表 gnb_core->ipv4_node_map = gnb_hash32_create(gnb_core->heap, 1024, 1024); //以节点的subnet(uint32)作为key的 node 表 gnb_core->subneta_node_map = gnb_hash32_create(gnb_core->heap, 1024, 1024); gnb_core->subnetb_node_map = gnb_hash32_create(gnb_core->heap, 1024, 1024); gnb_core->subnetc_node_map = gnb_hash32_create(gnb_core->heap, 1024, 1024); int64_t now_sec = gnb_timestamp_sec(); gnb_update_time_seed(gnb_core, now_sec); if ( 0 == gnb_core->conf->lite_mode ) { gnb_core->ctl_block->core_zone->local_uuid = gnb_core->conf->local_uuid; if ( 0==gnb_core->conf->daemon ) { if ( 1==is_verbose ) { gnb_core->conf->console_log_level = 2; gnb_core->conf->core_log_level = 2; gnb_core->conf->pf_log_level = 2; gnb_core->conf->main_log_level = 2; gnb_core->conf->node_log_level = 2; gnb_core->conf->index_log_level = 2; gnb_core->conf->index_service_log_level = 2; gnb_core->conf->detect_log_level = 2; } if ( 1==is_trace ) { gnb_core->conf->console_log_level = 3; gnb_core->conf->core_log_level = 3; gnb_core->conf->pf_log_level = 3; gnb_core->conf->main_log_level = 3; gnb_core->conf->node_log_level = 3; gnb_core->conf->index_log_level = 3; gnb_core->conf->index_service_log_level = 3; gnb_core->conf->detect_log_level = 3; } } setup_log_ctx(gnb_core->conf, gnb_core->log); gnb_config_safe(gnb_core); } else { if ( 0==gnb_core->conf->daemon ) { if ( 1==is_verbose ) { gnb_core->conf->console_log_level = 2; gnb_core->conf->core_log_level = 2; gnb_core->conf->pf_log_level = 2; gnb_core->conf->main_log_level = 2; gnb_core->conf->node_log_level = 2; gnb_core->conf->index_log_level = 2; gnb_core->conf->index_service_log_level = 2; gnb_core->conf->detect_log_level = 2; } if ( 1==is_trace ) { gnb_core->conf->console_log_level = 3; gnb_core->conf->core_log_level = 3; gnb_core->conf->pf_log_level = 3; gnb_core->conf->main_log_level = 3; gnb_core->conf->node_log_level = 3; gnb_core->conf->index_log_level = 3; gnb_core->conf->index_service_log_level = 3; gnb_core->conf->detect_log_level = 3; } } gnb_config_lite(gnb_core); setup_log_ctx(gnb_core->conf, gnb_core->log); } log_out_description(gnb_core->log); void *memory = (void *)gnb_core->ctl_block->entry_table256; gnb_ctl_block_build_finish(memory); snprintf(gnb_core->ifname, 256, "%s", gnb_core->conf->ifname); if ( NULL==gnb_core->local_node ) { GNB_ERROR1(gnb_core->log, GNB_LOG_ID_CORE, "local node is miss\n"); return NULL; } gnb_core->tun_payload0 = (gnb_payload16_t *)gnb_core->ctl_block->core_zone->tun_payload_block; gnb_core->inet_payload0 = (gnb_payload16_t *)gnb_core->ctl_block->core_zone->inet_payload_block; gnb_core->tun_payload = (void *)gnb_core->tun_payload0 + GNB_PAYLOAD_BUFFER_PADDING_SIZE; gnb_core->inet_payload = (void *)gnb_core->inet_payload0 + GNB_PAYLOAD_BUFFER_PADDING_SIZE; #if defined(__FreeBSD__) gnb_core->drv = &gnb_tun_drv_freebsd; #endif #if defined(__APPLE__) gnb_core->drv = &gnb_tun_drv_darwin; #endif #if defined(__OpenBSD__) gnb_core->drv = &gnb_tun_drv_openbsd; #endif #if defined(__linux__) gnb_core->drv = &gnb_tun_drv_linux; #endif #if defined(_WIN32) if ( GNB_IF_DRV_TYPE_TAP_WINDOWS == conf->if_drv ) { gnb_core->drv = &gnb_tun_drv_win32; } else if ( GNB_IF_DRV_TYPE_TAP_WINTUN == conf->if_drv ) { gnb_core->drv = &gnb_tun_drv_wintun; } else { gnb_core->drv = &gnb_tun_drv_win32; } #endif gnb_pf_status_strings_init(); if ( gnb_core->conf->activate_tun ) { gnb_core->drv->init_tun(gnb_core); } if ( gnb_core->conf->activate_node_worker ) { gnb_core->node_worker = gnb_worker_init("gnb_node_worker", gnb_core); } if ( gnb_core->conf->activate_index_worker ) { if ( 1 == gnb_core->conf->safe_index && 0 == gnb_core->conf->lite_mode ) { gnb_core->index_worker = gnb_worker_init("gnb_secure_index_worker", gnb_core); } else { gnb_core->index_worker = gnb_worker_init("gnb_index_worker", gnb_core); } } if ( gnb_core->conf->activate_detect_worker ) { gnb_core->detect_worker = gnb_worker_init("gnb_detect_worker", gnb_core); } if ( gnb_core->conf->activate_index_service_worker ) { if ( 1 == gnb_core->conf->safe_index ) { gnb_core->index_service_worker = gnb_worker_init("gnb_secure_index_service_worker", gnb_core); } else { gnb_core->index_service_worker = gnb_worker_init("gnb_index_service_worker", gnb_core); } } if ( gnb_core->conf->pf_worker_num > 0 ) { gnb_core->pf_worker_ring = (gnb_worker_ring_t *)gnb_heap_alloc(gnb_core->heap, sizeof(gnb_worker_ring_t) + sizeof(gnb_worker_t)*gnb_core->conf->pf_worker_num); gnb_core->pf_worker_ring->size = gnb_core->conf->pf_worker_num; for ( gnb_core->pf_worker_ring->cur_idx=0; gnb_core->pf_worker_ring->cur_idx < gnb_core->pf_worker_ring->size; gnb_core->pf_worker_ring->cur_idx++ ) { gnb_core->pf_worker_ring->worker[gnb_core->pf_worker_ring->cur_idx] = gnb_worker_init("gnb_pf_worker", gnb_core); } gnb_core->pf_worker_ring->cur_idx=0; } else { gnb_core->pf_worker_ring = (gnb_worker_ring_t *)gnb_heap_alloc(gnb_core->heap, sizeof(gnb_worker_ring_t) ); gnb_core->pf_worker_ring->size = 0; } gnb_core->primary_worker = gnb_worker_init("gnb_primary_worker", gnb_core); return gnb_core; } gnb_core_t* gnb_core_index_service_create(gnb_conf_t *conf){ gnb_core_t *gnb_core; gnb_heap_t *heap = gnb_heap_create(8192); gnb_core = gnb_heap_alloc(heap, sizeof(gnb_core_t)); memset(gnb_core, 0, sizeof(gnb_core_t)); gnb_core->heap = heap; init_ctl_block(gnb_core, conf); gnb_core->conf = &gnb_core->ctl_block->conf_zone->conf_st; memcpy(gnb_core->conf, conf, sizeof(gnb_conf_t)); gnb_core->log = &gnb_core->ctl_block->core_zone->log_ctx_st; gnb_log_ctx_t *log = gnb_log_ctx_create(); memcpy(gnb_core->log, log, sizeof(gnb_log_ctx_t)); free(log); gnb_core->ed25519_private_key = gnb_core->ctl_block->core_zone->ed25519_private_key; gnb_core->ed25519_public_key = gnb_core->ctl_block->core_zone->ed25519_public_key; gnb_core->ifname = (char *)gnb_core->ctl_block->core_zone->ifname; gnb_core->if_device_string = (char *)gnb_core->ctl_block->core_zone->if_device_string; if ( 0==conf->daemon ) { if ( 1==is_verbose ) { gnb_core->conf->console_log_level = 2; gnb_core->conf->core_log_level = 2; gnb_core->conf->pf_log_level = 2; gnb_core->conf->main_log_level = 2; gnb_core->conf->node_log_level = 2; gnb_core->conf->index_log_level = 2; gnb_core->conf->index_service_log_level = 2; gnb_core->conf->detect_log_level = 2; } if ( 1==is_trace ) { gnb_core->conf->console_log_level = 3; gnb_core->conf->core_log_level = 3; gnb_core->conf->pf_log_level = 3; gnb_core->conf->main_log_level = 3; gnb_core->conf->node_log_level = 3; gnb_core->conf->index_log_level = 3; gnb_core->conf->index_service_log_level = 3; gnb_core->conf->detect_log_level = 3; } if ( 1==gnb_core->conf->if_dump ) { gnb_core->conf->console_log_level = 3; gnb_core->conf->pf_log_level = 3; } } setup_log_ctx(gnb_core->conf, gnb_core->log); log_out_description(gnb_core->log); void *memory = (void *)gnb_core->ctl_block->entry_table256; gnb_ctl_block_build_finish(memory); snprintf(gnb_core->ifname,256,"%s", gnb_core->conf->ifname); gnb_core->tun_payload0 = (gnb_payload16_t *)gnb_core->ctl_block->core_zone->tun_payload_block; gnb_core->inet_payload0 = (gnb_payload16_t *)gnb_core->ctl_block->core_zone->inet_payload_block; gnb_core->tun_payload = gnb_core->tun_payload0 + GNB_PAYLOAD_BUFFER_PADDING_SIZE; gnb_core->inet_payload = gnb_core->inet_payload0 + GNB_PAYLOAD_BUFFER_PADDING_SIZE; gnb_core->index_service_worker = gnb_worker_init("gnb_index_service_worker", gnb_core); gnb_core->primary_worker = gnb_worker_init("gnb_primary_worker", gnb_core); return gnb_core; } void gnb_core_release(gnb_core_t *gnb_core){ //gnb_core 结构体内还有一些成员内存没做释放处理 if ( gnb_core->conf->public_index_service ) { goto PUBLIC_INDEX_RELEASE; } PUBLIC_INDEX_RELEASE: gnb_heap_free(gnb_core->heap ,gnb_core); } void gnb_core_index_service_start(gnb_core_t *gnb_core){ int ret; GNB_LOG1(gnb_core->log, GNB_LOG_ID_CORE,"GNB Public Index Service Start.....\n"); gnb_core->index_service_worker->start(gnb_core->index_service_worker); GNB_LOG1(gnb_core->log, GNB_LOG_ID_CORE,"%s start\n", gnb_core->index_service_worker->name); gnb_core->primary_worker->start(gnb_core->primary_worker); GNB_LOG1(gnb_core->log, GNB_LOG_ID_CORE,"%s start\n", gnb_core->primary_worker->name); } void gnb_core_start(gnb_core_t *gnb_core){ int ret; int i; GNB_LOG1(gnb_core->log, GNB_LOG_ID_CORE, "Start.....\n"); gnb_setup_env(gnb_core); update_node_crypto_key(gnb_core, 1); if ( gnb_core->conf->activate_tun ) { ret = gnb_core->drv->open_tun(gnb_core); if ( 0!=ret ) { if ( -1 == ret ) { GNB_LOG1(gnb_core->log, GNB_LOG_ID_CORE, "if[%s] already open\n", gnb_core->ifname); } else { GNB_LOG1(gnb_core->log, GNB_LOG_ID_CORE, "if[%s] error\n", gnb_core->ifname); } return; } GNB_LOG1(gnb_core->log, GNB_LOG_ID_CORE,"if[%s] opened\n", gnb_core->ifname); GNB_LOG1(gnb_core->log, GNB_LOG_ID_CORE,"node[%llu] ipv4[%s]\n", gnb_core->local_node->uuid64, GNB_ADDR4STR_PLAINTEXT1(&gnb_core->local_node->tun_addr4)); for ( i=0; ipf_worker_ring->size; i++ ) { gnb_core->pf_worker_ring->worker[i]->start(gnb_core->pf_worker_ring->worker[i]); GNB_LOG1(gnb_core->log, GNB_LOG_ID_CORE, "start packet filter worker [%s]\n", gnb_core->pf_worker_ring->worker[i]->name); } } if ( gnb_core->conf->activate_index_worker ) { gnb_core->index_worker->start(gnb_core->index_worker); GNB_LOG1(gnb_core->log, GNB_LOG_ID_CORE,"%s start\n", gnb_core->index_worker->name); } if ( gnb_core->conf->activate_detect_worker ) { gnb_core->detect_worker->start(gnb_core->detect_worker); GNB_LOG1(gnb_core->log, GNB_LOG_ID_CORE,"%s start\n", gnb_core->detect_worker->name); } if ( gnb_core->conf->activate_index_service_worker ) { gnb_core->index_service_worker->start(gnb_core->index_service_worker); GNB_LOG1(gnb_core->log, GNB_LOG_ID_CORE,"%s start\n", gnb_core->index_service_worker->name); } if ( gnb_core->conf->activate_node_worker ) { gnb_core->node_worker->start(gnb_core->node_worker); GNB_LOG1(gnb_core->log, GNB_LOG_ID_CORE,"%s start\n", gnb_core->node_worker->name); } gnb_core->primary_worker->start(gnb_core->primary_worker); GNB_LOG1(gnb_core->log, GNB_LOG_ID_CORE,"%s start\n", gnb_core->primary_worker->name); } void gnb_core_stop(gnb_core_t *gnb_core){ int i; gnb_core->primary_worker->stop(gnb_core->primary_worker); if ( gnb_core->conf->activate_tun ) { for ( i=0; ipf_worker_ring->size; i++ ) { gnb_core->pf_worker_ring->worker[i]->stop(gnb_core->pf_worker_ring->worker[i]); } gnb_core->drv->close_tun(gnb_core); } if ( gnb_core->conf->activate_index_worker ) { gnb_core->index_worker->stop(gnb_core->index_worker); } if ( gnb_core->conf->activate_detect_worker ) { gnb_core->detect_worker->stop(gnb_core->detect_worker); } if ( gnb_core->conf->activate_index_service_worker ) { gnb_core->index_service_worker->stop(gnb_core->index_service_worker); } if ( gnb_core->conf->activate_node_worker ) { gnb_core->node_worker->stop(gnb_core->node_worker); } gnb_core->loop_flag = 0; #ifdef __UNIX_LIKE_OS__ for ( i=0; iconf->udp6_socket_num; i++ ) { close(gnb_core->udp_ipv6_sockets[i]); } for ( i=0; iconf->udp4_socket_num; i++ ) { close(gnb_core->udp_ipv4_sockets[i]); } #endif #ifdef _WIN32 for ( i=0; iconf->udp6_socket_num; i++ ) { closesocket(gnb_core->udp_ipv6_sockets[i]); } for ( i=0; iconf->udp4_socket_num; i++ ) { closesocket(gnb_core->udp_ipv4_sockets[i]); } #endif GNB_LOG1(gnb_core->log, GNB_LOG_ID_CORE,"if[%s] closeed\n", gnb_core->ifname); } #ifdef __UNIX_LIKE_OS__ static void exec_es(gnb_core_t *gnb_core) { pid_t pid_gnb_es = 0; int ret; char gnb_es_bin_path[PATH_MAX+NAME_MAX]; char es_arg_string[GNB_ARG_STRING_MAX_SIZE]; snprintf(gnb_es_bin_path, PATH_MAX+NAME_MAX, "%s/gnb_es", gnb_core->conf->binary_dir); ret = gnb_arg_list_to_string(gnb_es_arg_list, es_arg_string, GNB_ARG_STRING_MAX_SIZE); if ( 0 != ret ) { GNB_LOG3(gnb_core->log, GNB_LOG_ID_CORE, "gnb_es argv error, skip exec '%s'\n", gnb_es_bin_path); return; } GNB_LOG3(gnb_core->log, GNB_LOG_ID_CORE, "exec gnb_es argv '%s'\n", es_arg_string); pid_gnb_es = gnb_exec(gnb_es_bin_path, gnb_core->conf->binary_dir, gnb_es_arg_list, GNB_EXEC_WAIT); if ( -1 == pid_gnb_es ) { return; } } #endif #ifdef _WIN32 static void exec_es(gnb_core_t *gnb_core) { DWORD pid_gnb_es = 0; int ret; char gnb_es_bin_path[PATH_MAX+NAME_MAX]; char es_arg_string[GNB_ARG_STRING_MAX_SIZE]; snprintf(gnb_es_bin_path, PATH_MAX+NAME_MAX, "%s\\gnb_es.exe", gnb_core->conf->binary_dir); ret = gnb_arg_list_to_string(gnb_es_arg_list, es_arg_string, GNB_ARG_STRING_MAX_SIZE); if ( 0 != ret ) { GNB_LOG3(gnb_core->log, GNB_LOG_ID_CORE, "gnb_es argv error, skip exec '%s'\n", gnb_es_bin_path); return; } GNB_LOG3(gnb_core->log, GNB_LOG_ID_CORE, "exec gnb_es argv '%s'\n", es_arg_string); pid_gnb_es = gnb_exec(gnb_es_bin_path, gnb_core->conf->binary_dir, gnb_es_arg_list, GNB_EXEC_BACKGROUND|GNB_EXEC_WAIT ); } #endif static void exec_loop_script(gnb_core_t *gnb_core, const char *script_file_name){ char script_dir[PATH_MAX]; char script_file[PATH_MAX+NAME_MAX]; int arg_list_size = 1; pid_t pid = 0; gnb_arg_list_t *arg_list = (gnb_arg_list_t *)alloca( sizeof(gnb_arg_list_t) + sizeof(char *) * arg_list_size ); arg_list->size = arg_list_size; arg_list->argc = 0; strncpy(script_dir, gnb_core->conf->conf_dir, PATH_MAX); strncat(script_dir, "/scripts", PATH_MAX-strlen(script_dir)); snprintf(script_file, PATH_MAX+NAME_MAX,"%s/%s", script_dir, script_file_name); gnb_arg_append(arg_list, script_file); pid = gnb_exec(script_file, script_dir, arg_list, GNB_EXEC_WAIT); return; } #define GNB_EXEC_ES_INTERVAL_TIME_SEC (60*5) #define GNB_EXEC_SCRIPT_INTERVAL_TIME_SEC (60) void primary_process_loop( gnb_core_t *gnb_core ){ int ret; uint64_t last_exec_es_ts_sec = 0; uint64_t last_exec_loop_script_ts_sec = 0; do{ ret = gettimeofday(&gnb_core->now_timeval,NULL); if ( 0!=ret ) { perror("gettimeofday"); exit(1); } gnb_core->now_time_sec = gnb_core->now_timeval.tv_sec; gnb_core->now_time_usec = gnb_core->now_timeval.tv_sec * 1000000 + gnb_core->now_timeval.tv_usec; gnb_core->ctl_block->status_zone->keep_alive_ts_sec = (uint64_t)gnb_core->now_timeval.tv_sec; gnb_log_file_rotate(gnb_core->log); #ifdef __UNIX_LIKE_OS__ sleep(1); #endif #ifdef _WIN32 Sleep(1000); #endif if ( gnb_core->ctl_block->status_zone->keep_alive_ts_sec - last_exec_es_ts_sec > GNB_EXEC_ES_INTERVAL_TIME_SEC ) { if ( 0 == gnb_core->conf->public_index_service ) { exec_es(gnb_core); } last_exec_es_ts_sec = gnb_core->ctl_block->status_zone->keep_alive_ts_sec; } if ( gnb_core->ctl_block->status_zone->keep_alive_ts_sec - last_exec_loop_script_ts_sec > GNB_EXEC_SCRIPT_INTERVAL_TIME_SEC ) { #if defined(__FreeBSD__) exec_loop_script(gnb_core,"if_loop_freebsd.sh"); #endif #if defined(__APPLE__) exec_loop_script(gnb_core,"if_loop_darwin.sh"); #endif #if defined(__OpenBSD__) exec_loop_script(gnb_core,"if_loop_openbsd.sh"); #endif #if defined(__linux__) exec_loop_script(gnb_core,"if_loop_linux.sh"); #endif #if defined(_WIN32) #endif last_exec_loop_script_ts_sec = gnb_core->ctl_block->status_zone->keep_alive_ts_sec; } }while(1); } opengnb-ver1.6.0.a/src/gnb_core.h000077500000000000000000000017421500454252100166250ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 . */ #ifndef GNB_CORE_H #define GNB_CORE_H #include "gnb.h" gnb_core_t* gnb_core_create(gnb_conf_t *conf); void gnb_core_start(gnb_core_t *gnb_core); void gnb_core_stop(gnb_core_t *gnb_core); gnb_core_t * gnb_core_index_service_create(gnb_conf_t *conf); void gnb_core_index_service_start(gnb_core_t *gnb_core); #endif opengnb-ver1.6.0.a/src/gnb_core_frame_type_defs.h000077500000000000000000000053051500454252100220400ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 . */ #ifndef GNB_CORE_FRAME_TYPE_DEFS_H #define GNB_CORE_FRAME_TYPE_DEFS_H #define GNB_PAYLOAD_TYPE_UR0 (0x3) #define GNB_PAYLOAD_TYPE_IPFRAME (0x4) #define GNB_PAYLOAD_SUB_TYPE_IPFRAME_INIT (0x0) #define GNB_PAYLOAD_SUB_TYPE_IPFRAME_STD (0x1) #define GNB_PAYLOAD_SUB_TYPE_IPFRAME_RELAY (0x1 << 1) #define GNB_PAYLOAD_SUB_TYPE_IPFRAME_UNIFIED (0x1 << 2) #define GNB_PAYLOAD_SUB_TYPE_IPFRAME_UNIFIED_MULTI_PATH (0x1 << 3) #define GNB_PAYLOAD_SUB_TYPE_IPFRAME_ZIP (0x1 << 4) #define GNB_PAYLOAD_TYPE_INDEX (0x8) #define PAYLOAD_SUB_TYPE_POST_ADDR (0x1) #define PAYLOAD_SUB_TYPE_ECHO_ADDR (0x2) #define PAYLOAD_SUB_TYPE_REQUEST_ADDR (0x3) #define PAYLOAD_SUB_TYPE_PUSH_ADDR (0x4) #define PAYLOAD_SUB_TYPE_DETECT_ADDR (0x5) #define GNB_PAYLOAD_TYPE_NODE (0x9) #define PAYLOAD_SUB_TYPE_PING (0x1) #define PAYLOAD_SUB_TYPE_PONG (0x2) #define PAYLOAD_SUB_TYPE_PONG2 (0x3) #define PAYLOAD_SUB_TYPE_LAN_PING (0x4) #define PAYLOAD_SUB_TYPE_NODE_UNIFIED_NOTIFY (0x5) #define GNB_PAYLOAD_TYPE_LAN_DISCOVER (0x43) #define GNB_PAYLOAD_TYPE_UDPLOG (0x44) #define GNB_ES_PAYLOAD_TYPE_UDPLOG (0x45) #define GNB_PAYLOAD_TYPE_UR1 (0x46) #define GNB_PAYLOAD_SUB_TYPE_UR1_UNSET (0x0) //IPV6:bit=0,IPV4:bit=1 #define GNB_PAYLOAD_SUB_TYPE_UR1_SRC_ADDRESS6 (0x0) #define GNB_PAYLOAD_SUB_TYPE_UR1_SRC_ADDRESS4 (0x1) //IPV6:bit=0,IPV4:bit=1 #define GNB_PAYLOAD_SUB_TYPE_UR1_DST_ADDRESS6 (0x0) #define GNB_PAYLOAD_SUB_TYPE_UR1_DST_ADDRESS4 (0x1 << 1) //不转发header:bit=0,转发header:bit=1 #define GNB_PAYLOAD_SUB_TYPE_UR1_NOHEADER (0x0) #define GNB_PAYLOAD_SUB_TYPE_UR1_HEADER (0x1 << 2) #define GNB_PAYLOAD_SUB_TYPE_UR1_STD (0x1 << 3) #define GNB_PAYLOAD_SUB_TYPE_UR1_UNIFIED (0x1 << 4) #define ED25519_SIGN_SIZE 64 #endif opengnb-ver1.6.0.a/src/gnb_ctl_block.c000077500000000000000000000145521500454252100176270ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 #include #include #include #include "gnb_ctl_block.h" #include "gnb_mmap.h" #include "gnb_time.h" #include "gnb_block.h" //entry_table256 的类型是 uint32_t, //索引从2 开始,留出 0,1 两个 uint32_t 共 8个字节 //用于 file magic number 和 记录文件的大小 #define GNB_CTL_MAGIC_NUMBER 2 #define GNB_CTL_CONF 3 #define GNB_CTL_CORE 4 #define GNB_CTL_STATUS 5 #define GNB_CTL_NODE 6 ssize_t gnb_ctl_file_size(const char *filename) { struct stat s; int ret; ret = stat(filename,&s); if ( 0 != ret ) { return -1; } return s.st_size; } gnb_ctl_block_t *gnb_ctl_block_build(void *memory, uint32_t payload_block_size, size_t node_num, uint8_t pf_worker_num){ uint32_t off_set = sizeof(uint32_t)*256; gnb_block32_t *block; gnb_ctl_block_t *ctl_block = (gnb_ctl_block_t *)malloc(sizeof(gnb_ctl_block_t)); ctl_block->entry_table256 = memory; //向量表清零 memset(ctl_block->entry_table256, 0, sizeof(uint32_t)*256); ctl_block->entry_table256[GNB_CTL_MAGIC_NUMBER] = off_set; block = memory + ctl_block->entry_table256[GNB_CTL_MAGIC_NUMBER]; block->size = sizeof(gnb_ctl_magic_number_t); ctl_block->magic_number = (gnb_ctl_magic_number_t *)block->data; off_set += sizeof(gnb_block32_t) + sizeof(gnb_ctl_magic_number_t); snprintf((char *)ctl_block->magic_number->data, 16, "%s", "GNB Ver1.4.5.a"); ctl_block->entry_table256[GNB_CTL_CONF] = off_set; block = memory + ctl_block->entry_table256[GNB_CTL_CONF]; block->size = sizeof(gnb_ctl_conf_zone_t); ctl_block->conf_zone = (gnb_ctl_conf_zone_t *)block->data; off_set += sizeof(gnb_block32_t) + sizeof(gnb_ctl_conf_zone_t); snprintf((char *)ctl_block->conf_zone->name, 8, "%s", "CONF"); ctl_block->entry_table256[GNB_CTL_CORE] = off_set; block = memory + ctl_block->entry_table256[GNB_CTL_CORE]; block->size = sizeof(gnb_ctl_core_zone_t) + ( sizeof(gnb_payload16_t) + payload_block_size + sizeof(gnb_payload16_t) + payload_block_size ) * (1+pf_worker_num); ctl_block->core_zone = (gnb_ctl_core_zone_t *)block->data; off_set += sizeof(gnb_block32_t) + sizeof(gnb_ctl_core_zone_t) + ( sizeof(gnb_payload16_t) + payload_block_size + sizeof(gnb_payload16_t) + payload_block_size ) * (1+pf_worker_num); ctl_block->entry_table256[GNB_CTL_STATUS] = off_set; block = memory + ctl_block->entry_table256[GNB_CTL_STATUS]; block->size = sizeof(gnb_ctl_status_zone_t); ctl_block->status_zone = (gnb_ctl_status_zone_t *)block->data; off_set += sizeof(gnb_block32_t) + sizeof(gnb_ctl_status_zone_t); ctl_block->entry_table256[GNB_CTL_NODE] = off_set; block = memory + ctl_block->entry_table256[GNB_CTL_NODE]; block->size = sizeof(gnb_ctl_node_zone_t) + sizeof(gnb_node_t)*node_num; ctl_block->node_zone = (gnb_ctl_node_zone_t *)block->data; off_set += sizeof(gnb_block32_t) + sizeof(gnb_ctl_node_zone_t) + sizeof(gnb_node_t)*node_num; snprintf((char *)ctl_block->node_zone->name, 8, "%s", "NODE"); ctl_block->node_zone->node_num = node_num; return ctl_block; } void gnb_ctl_block_build_finish(void *memory){ gnb_ctl_block_t ctl_block_st; gnb_ctl_block_setup(&ctl_block_st, memory); ctl_block_st.status_zone->keep_alive_ts_sec = gnb_timestamp_sec(); //写入 GNB 确定共享内存初始化完成 char *mem_magic_number = memory; mem_magic_number[0] = 'G'; mem_magic_number[1] = 'N'; mem_magic_number[2] = 'B'; } void gnb_ctl_block_setup(gnb_ctl_block_t *ctl_block, void *memory){ gnb_block32_t *block; ctl_block->entry_table256 = memory; block = memory + ctl_block->entry_table256[GNB_CTL_MAGIC_NUMBER]; ctl_block->magic_number = (gnb_ctl_magic_number_t *)block->data; block = memory + ctl_block->entry_table256[GNB_CTL_CONF]; ctl_block->conf_zone = (gnb_ctl_conf_zone_t *)block->data; block = memory + ctl_block->entry_table256[GNB_CTL_CORE]; ctl_block->core_zone = (gnb_ctl_core_zone_t *)block->data; block = memory + ctl_block->entry_table256[GNB_CTL_STATUS]; ctl_block->status_zone = (gnb_ctl_status_zone_t *)block->data; block = memory + ctl_block->entry_table256[GNB_CTL_NODE]; ctl_block->node_zone = (gnb_ctl_node_zone_t *)block->data; } /* flag = 0 readonly */ gnb_ctl_block_t *gnb_get_ctl_block(const char *ctl_block_file, int flag){ ssize_t ctl_file_size = 0; uint64_t now_sec; gnb_mmap_block_t *mmap_block; void *memory; char *mem_magic_number; gnb_ctl_block_t *ctl_block; ctl_file_size = gnb_ctl_file_size(ctl_block_file); if ( ctl_file_size < (ssize_t)MIN_CTL_BLOCK_FILE_SIZE ) { return NULL; } mmap_block = gnb_mmap_create(ctl_block_file, ctl_file_size, GNB_MMAP_TYPE_READWRITE); if ( NULL == mmap_block ) { return NULL; } memory = gnb_mmap_get_block(mmap_block); mem_magic_number = (char *)memory; if ( 'G' != mem_magic_number[0] || 'N' != mem_magic_number[1] || 'B' != mem_magic_number[2] ) { return NULL; } now_sec = gnb_timestamp_sec(); ctl_block = (gnb_ctl_block_t *)malloc(sizeof(gnb_ctl_block_t)); gnb_ctl_block_setup(ctl_block, memory); ctl_block->mmap_block = mmap_block; if ( 0 == flag ) { return ctl_block; } if ( now_sec < ctl_block->status_zone->keep_alive_ts_sec ) { goto finish_error; } if ( now_sec == ctl_block->status_zone->keep_alive_ts_sec ) { return ctl_block; } if ( (now_sec - ctl_block->status_zone->keep_alive_ts_sec) < GNB_CTL_KEEP_ALIVE_TS ) { return ctl_block; } finish_error: gnb_mmap_release(mmap_block); free(ctl_block); return NULL; } opengnb-ver1.6.0.a/src/gnb_ctl_block.h000077500000000000000000000064431500454252100176340ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 . */ #ifndef GNB_CTL_BLOCK_H #define GNB_CTL_BLOCK_H #include #include "gnb_mmap.h" #include "gnb_payload16.h" #include "gnb_conf_type.h" #include "gnb_node_type.h" #include "gnb_log_type.h" #define GNB_MAX_PAYLOAD_BLOCK_SIZE 1024*64 #define GNB_PAYLOAD_BUFFER_PADDING_SIZE 1024 #define CTL_BLOCK_ES_MAGIC_IDX 3 #define CTL_BLOCK_VT_MAGIC_IDX 4 typedef struct _gnb_ctl_magic_number_t { unsigned char data[16]; }gnb_ctl_magic_number_t; typedef struct _gnb_ctl_conf_zone_t { unsigned char name[8]; gnb_conf_t conf_st; }gnb_ctl_conf_zone_t; typedef struct _gnb_ctl_core_zone_t { unsigned char name[8]; gnb_uuid_t local_uuid; unsigned char ed25519_private_key[64]; unsigned char ed25519_public_key[32]; uint32_t tun_if_id; unsigned char ifname[256]; unsigned char if_device_string[256]; unsigned char wan6_addr[16]; uint16_t wan6_port; //网络字节序 unsigned char wan4_addr[4]; uint16_t wan4_port; //网络字节序 gnb_log_ctx_t log_ctx_st; unsigned char index_address_block[ sizeof(gnb_address_list_t) + sizeof(gnb_address_t) * GNB_MAX_ADDR_RING ]; unsigned char ufwd_address_block[ sizeof(gnb_address_list_t) + sizeof(gnb_address_t) * 16 ]; unsigned char tun_payload_block[ GNB_PAYLOAD_BUFFER_PADDING_SIZE + sizeof(gnb_payload16_t) + GNB_MAX_PAYLOAD_BLOCK_SIZE ]; unsigned char inet_payload_block[ GNB_PAYLOAD_BUFFER_PADDING_SIZE + sizeof(gnb_payload16_t) + GNB_MAX_PAYLOAD_BLOCK_SIZE ]; unsigned char pf_worker_payload_blocks[0]; }gnb_ctl_core_zone_t; typedef struct _gnb_ctl_status_zone_t { uint64_t keep_alive_ts_sec; }gnb_ctl_status_zone_t; typedef struct _gnb_ctl_node_zone_t { unsigned char name[8]; int node_num; gnb_node_t node[0]; }gnb_ctl_node_zone_t; typedef struct _gnb_ctl_block_t { uint32_t *entry_table256; gnb_ctl_magic_number_t *magic_number; gnb_ctl_conf_zone_t *conf_zone; gnb_ctl_core_zone_t *core_zone; gnb_ctl_status_zone_t *status_zone; gnb_ctl_node_zone_t *node_zone; gnb_mmap_block_t *mmap_block; }gnb_ctl_block_t; ssize_t gnb_ctl_file_size(const char *filename); gnb_ctl_block_t *gnb_ctl_block_build(void *memory, uint32_t payload_block_size, size_t node_num, uint8_t pf_worker_num); void gnb_ctl_block_build_finish(void *memory); void gnb_ctl_block_setup(gnb_ctl_block_t *ctl_block, void *memory); gnb_ctl_block_t *gnb_get_ctl_block(const char *ctl_block_file, int flag); #define MIN_CTL_BLOCK_FILE_SIZE (sizeof(uint32_t)*256 + sizeof(gnb_ctl_magic_number_t) + sizeof(gnb_ctl_conf_zone_t) + sizeof(gnb_ctl_core_zone_t) + sizeof(gnb_ctl_status_zone_t) + sizeof(gnb_ctl_node_zone_t) + sizeof(gnb_node_t)) #define GNB_CTL_KEEP_ALIVE_TS 15 #endif opengnb-ver1.6.0.a/src/gnb_ctl_block_set.c000077500000000000000000000020261500454252100204730ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 #include #include #include #include "gnb_conf_type.h" #include "gnb_node_type.h" #include "gnb_address.h" #include "gnb_binary.h" #include "gnb_time.h" #include "gnb_udp.h" #include "gnb_ctl_block.h" #include "ed25519/sha512.h" #ifdef _WIN32 #include #include #include #endif opengnb-ver1.6.0.a/src/gnb_daemon.c000077500000000000000000000032271500454252100171330ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 #include #include #include #include "gnb_platform.h" #ifdef __UNIX_LIKE_OS__ #include #include #include #include #endif #ifdef __UNIX_LIKE_OS__ int gnb_daemon(){ int ret; int fd; pid_t pid; pid = fork(); if ( 0 != pid ) { exit(0); } setsid(); signal(SIGHUP,SIG_IGN); pid = fork(); if ( 0 != pid ) { exit(0); } ret = chdir("/"); umask(0); fd = open("/dev/null", O_RDWR); if ( -1 == fd ) { return -1; } ret = dup2(fd, STDIN_FILENO); if ( -1 == ret ) { return -2; } ret = dup2(fd, STDOUT_FILENO); if ( -1 == ret ) { return -3; } return 0; } void save_pid(const char *pid_file){ FILE *file; file = fopen(pid_file,"w"); if ( NULL==file ) { printf("open pid file[%s] err\n",pid_file); exit(1); } int pid = getpid(); fprintf(file,"%d",pid); fclose(file); } #endif opengnb-ver1.6.0.a/src/gnb_detect_worker.c000077500000000000000000000271271500454252100205360ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 #include #ifdef _WIN32 #define _POSIX #define __USE_MINGW_ALARM #endif #include #include #include #include #include #include #include #include "gnb.h" #include "gnb_node.h" #include "gnb_worker.h" #include "gnb_time.h" #include "gnb_binary.h" #include "gnb_index_frame_type.h" #include "ed25519/ed25519.h" #include "crypto/xor/xor.h" typedef struct _detect_worker_ctx_t{ gnb_core_t *gnb_core; gnb_payload16_t *index_frame_payload; struct timeval now_timeval; uint64_t now_time_sec; uint64_t now_time_usec; uint8_t is_send_detect; pthread_t thread_worker; }detect_worker_ctx_t; #define GNB_DETECT_PUSH_ADDRESS_INTERVAL_SEC 145 static void detect_node_address(gnb_worker_t *gnb_detect_worker, gnb_node_t *node, uint32_t interval_usec){ detect_worker_ctx_t *detect_worker_ctx = gnb_detect_worker->ctx; gnb_core_t *gnb_core = detect_worker_ctx->gnb_core; gnb_address_t address_st; if ( 0 == node->detect_port4 ) { return; } gnb_node_t *dst_node; memcpy(&address_st.m_address4, &node->detect_addr4, 4); address_st.port = htons(node->detect_port4); address_st.type = AF_INET; detect_worker_ctx->index_frame_payload->sub_type = PAYLOAD_SUB_TYPE_DETECT_ADDR; gnb_payload16_set_data_len( detect_worker_ctx->index_frame_payload, sizeof(detect_addr_frame_t) ); detect_addr_frame_t *detect_addr_frame = (detect_addr_frame_t *)detect_worker_ctx->index_frame_payload->data; memset(detect_addr_frame, 0, sizeof(detect_addr_frame_t)); detect_addr_frame->data.arg0 = 'd'; memcpy(detect_addr_frame->data.src_key512, gnb_core->local_node->key512, 64); detect_addr_frame->data.src_uuid64 = gnb_htonll(gnb_core->local_node->uuid64); detect_addr_frame->data.dst_uuid64 = gnb_htonll(node->uuid64); detect_addr_frame->data.src_ts_usec = gnb_htonll(detect_worker_ctx->now_time_usec); //debug_text snprintf(detect_addr_frame->data.text,32,"[%llu]FULL_DETECT[%llu]", gnb_core->local_node->uuid64, node->uuid64); if ( 1 == gnb_core->conf->safe_index && 0 == gnb_core->conf->lite_mode ) { dst_node = GNB_HASH32_UINT64_GET_PTR(gnb_core->uuid_node_map, node->uuid64); if ( NULL==dst_node ) { GNB_LOG3(gnb_core->log, GNB_LOG_ID_INDEX_WORKER, "SEND DETECT ADDR dst=%llu nodeid not found!\n", node->uuid64); return; } xor_crypto(dst_node->crypto_key, (unsigned char *)&detect_addr_frame->data, sizeof(struct detect_addr_frame_data)); ed25519_sign(detect_addr_frame->src_sign, (const unsigned char *)&detect_addr_frame->data, sizeof(struct detect_addr_frame_data), gnb_core->ed25519_public_key, gnb_core->ed25519_private_key); } detect_addr_frame->node_uuid64 = gnb_htonll(gnb_core->local_node->uuid64); address_st.port = htons(node->detect_port4); gnb_send_to_address_through_all_sockets(gnb_core, &address_st, detect_worker_ctx->index_frame_payload, interval_usec); detect_worker_ctx->is_send_detect = 1; node->last_send_detect_usec = detect_worker_ctx->now_time_usec; GNB_LOG4(gnb_core->log, GNB_LOG_ID_DETECT_WORKER, "Try node address [%llu]->[%llu]%s status=%d\n", gnb_core->local_node->uuid64, node->uuid64, GNB_IP_PORT_STR1(&address_st), node->udp_addr_status); } static void detect_node_set_address(gnb_worker_t *gnb_detect_worker, gnb_node_t *node){ detect_worker_ctx_t *detect_worker_ctx = gnb_detect_worker->ctx; gnb_core_t *gnb_core = detect_worker_ctx->gnb_core; gnb_address_list_t *address_list; address_list = (gnb_address_list_t *)&node->detect_address4_block; memcpy(&node->detect_addr4, &address_list->array[node->detect_address4_idx].m_address4, 4); if ( 0 == node->detect_addr4.s_addr ) { if ( 2==node->detect_address4_idx ) { node->detect_address4_idx = 0; node->last_detect_sec = detect_worker_ctx->now_time_sec; } else { node->detect_address4_idx += 1; } node->detect_port4 = gnb_core->conf->port_detect_start; return; } if ( node->detect_port4 < gnb_core->conf->port_detect_start ) { node->detect_port4 = gnb_core->conf->port_detect_start; } else { node->detect_port4 += 1; } if ( node->detect_port4 > gnb_core->conf->port_detect_end ) { if ( 2==node->detect_address4_idx ) { node->detect_address4_idx = 0; } else { node->detect_address4_idx += 1; } node->detect_port4 = gnb_core->conf->port_detect_start; } } static void detect_loop(gnb_worker_t *gnb_detect_worker){ detect_worker_ctx_t *detect_worker_ctx = gnb_detect_worker->ctx; gnb_core_t *gnb_core = detect_worker_ctx->gnb_core; gnb_node_t *node; uint64_t time_difference; uint64_t full_detect_time_difference; size_t num = gnb_core->ctl_block->node_zone->node_num; if ( 0==num ) { return; } int i; for ( i=0; ictl_block->node_zone->node[i]; if ( gnb_core->local_node->uuid64 == node->uuid64 ) { continue; } //如果本地节点带有 GNB_NODE_TYPE_SLIENCE 属性 将只探测带有 GNB_NODE_TYPE_FWD 属性的节点的地址 if ( (gnb_core->local_node->type & GNB_NODE_TYPE_SLIENCE) && !(node->type & GNB_NODE_TYPE_FWD) ) { GNB_LOG5(gnb_core->log, GNB_LOG_ID_DETECT_WORKER, "Skip Detect [%llu]->[%llu] node type is SLIENCE and not FWD\n", gnb_core->local_node->uuid64, node->uuid64); continue; } if ( (GNB_NODE_STATUS_IPV6_PONG | GNB_NODE_STATUS_IPV4_PONG) & node->udp_addr_status ) { GNB_LOG5(gnb_core->log, GNB_LOG_ID_DETECT_WORKER, "Skip Detect [%llu]->[%llu] already P2P status=%d\n", gnb_core->local_node->uuid64, node->uuid64, node->udp_addr_status); continue; } time_difference = detect_worker_ctx->now_time_sec - node->last_push_addr_sec; if ( time_difference > GNB_DETECT_PUSH_ADDRESS_INTERVAL_SEC ) { GNB_LOG5(gnb_core->log, GNB_LOG_ID_DETECT_WORKER, "Skip Detect [%llu]->[%llu] status=%d time_difference(%"PRIu64") > GNB_DETECT_PUSH_ADDRESS_INTERVAL_SEC(%"PRIu64") last_push_addr_sec=%"PRIu64"\n", gnb_core->local_node->uuid64, node->uuid64, node->udp_addr_status, time_difference, GNB_DETECT_PUSH_ADDRESS_INTERVAL_SEC, node->last_push_addr_sec); continue; } full_detect_time_difference = detect_worker_ctx->now_time_sec - node->last_full_detect_sec; if ( full_detect_time_difference < gnb_core->conf->full_detect_interval_sec ) { GNB_LOG5(gnb_core->log, GNB_LOG_ID_DETECT_WORKER, "Skip Detect [%llu]->[%llu] status=%d full_detect_time_difference(%"PRIu64") < full_detect_interval_sec(%"PRIu64") last_full_detect_sec=%"PRIu64"\n", gnb_core->local_node->uuid64, node->uuid64, node->udp_addr_status, full_detect_time_difference, gnb_core->conf->full_detect_interval_sec, node->last_full_detect_sec); continue; } if ( gnb_core->conf->address_detect_interval_usec > 0 ) { GNB_SLEEP_MILLISECOND( gnb_core->conf->address_detect_interval_usec/1000 ); } detect_node_set_address(gnb_detect_worker, node); if ( 0 == node->detect_addr4.s_addr ) { GNB_LOG5(gnb_core->log, GNB_LOG_ID_DETECT_WORKER, "Skip Detect [%llu]->[%llu] detect_addr4=0 status=%d \n", gnb_core->local_node->uuid64, node->uuid64, node->udp_addr_status); continue; } if ( gnb_core->conf->port_detect_start == node->detect_port4 ) { GNB_LOG3(gnb_core->log, GNB_LOG_ID_DETECT_WORKER, "#START FULL DECETE node[%llu] idx[%d]\n", node->uuid64, node->detect_address4_idx); } detect_node_address(gnb_detect_worker, node, gnb_core->conf->address_detect_interval_usec); if ( gnb_core->conf->port_detect_end == node->detect_port4 ) { node->last_full_detect_sec = detect_worker_ctx->now_time_sec; GNB_LOG3(gnb_core->log, GNB_LOG_ID_DETECT_WORKER, "#END FULL DECETE node[%llu] idx[%d]\n", node->uuid64, node->detect_address4_idx); } } } static void* thread_worker_func( void *data ) { int ret; gnb_worker_t *gnb_detect_worker = (gnb_worker_t *)data; detect_worker_ctx_t *detect_worker_ctx = gnb_detect_worker->ctx; gnb_core_t *gnb_core = detect_worker_ctx->gnb_core; gnb_detect_worker->thread_worker_flag = 1; gnb_detect_worker->thread_worker_run_flag = 1; gnb_worker_wait_primary_worker_started(gnb_core); GNB_LOG1(gnb_core->log, GNB_LOG_ID_DETECT_WORKER, "start %s success!\n", gnb_detect_worker->name); do{ gnb_worker_sync_time(&detect_worker_ctx->now_time_sec, &detect_worker_ctx->now_time_usec); if ( 0==gnb_core->index_address_ring.address_list->num ) { GNB_SLEEP_MILLISECOND(1000); continue; } detect_worker_ctx->is_send_detect = 0; detect_loop(gnb_detect_worker); if ( detect_worker_ctx->is_send_detect ) { GNB_SLEEP_MILLISECOND(1); } else { GNB_SLEEP_MILLISECOND(1000); } }while(gnb_detect_worker->thread_worker_flag); return NULL; } static void init(gnb_worker_t *gnb_worker, void *ctx){ gnb_core_t *gnb_core = (gnb_core_t *)ctx; detect_worker_ctx_t *detect_worker_ctx = (detect_worker_ctx_t *)gnb_heap_alloc(gnb_core->heap, sizeof(detect_worker_ctx_t)); memset(detect_worker_ctx, 0, sizeof(detect_worker_ctx_t)); detect_worker_ctx->index_frame_payload = (gnb_payload16_t *)gnb_heap_alloc(gnb_core->heap, gnb_core->conf->payload_block_size); detect_worker_ctx->index_frame_payload->type = GNB_PAYLOAD_TYPE_INDEX; detect_worker_ctx->gnb_core = (gnb_core_t *)ctx; gnb_worker->ctx = detect_worker_ctx; GNB_LOG1(gnb_core->log,GNB_LOG_ID_DETECT_WORKER,"%s init finish\n", gnb_worker->name); } static void release(gnb_worker_t *gnb_worker){ detect_worker_ctx_t *detect_worker_ctx = (detect_worker_ctx_t *)gnb_worker->ctx; gnb_core_t *gnb_core = detect_worker_ctx->gnb_core; } static int start(gnb_worker_t *gnb_worker){ detect_worker_ctx_t *detect_worker_ctx = gnb_worker->ctx; pthread_create(&detect_worker_ctx->thread_worker, NULL, thread_worker_func, gnb_worker); pthread_detach(detect_worker_ctx->thread_worker); return 0; } static int stop(gnb_worker_t *gnb_worker){ detect_worker_ctx_t *detect_worker_ctx = gnb_worker->ctx; gnb_core_t *gnb_core = detect_worker_ctx->gnb_core; gnb_worker_t *gnb_detect_worker = gnb_core->detect_worker; gnb_detect_worker->thread_worker_flag = 0; return 0; } static int notify(gnb_worker_t *gnb_worker){ return 0; } gnb_worker_t gnb_detect_worker_mod = { .name = "gnb_detect_worker", .init = init, .release = release, .start = start, .stop = stop, .notify = notify, .ctx = NULL }; opengnb-ver1.6.0.a/src/gnb_dir.c000077500000000000000000000311371500454252100164470ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 #include #include #include #include #include #include "gnb_platform.h" #include "gnb_dir.h" #if __UNIX_LIKE_OS__ #define GNB_FILE_SP '/' #endif #ifdef _WIN32 #define GNB_FILE_SP '\\' #ifndef NAME_MAX #define NAME_MAX 255 #endif #endif char *gnb_get_file_dir(char *in_file_name, char *file_dir) { #if __UNIX_LIKE_OS__ if ( NULL == realpath(in_file_name, file_dir) ) { return NULL; } #endif #ifdef _WIN32 if ( NULL == _fullpath(file_dir, in_file_name , PATH_MAX) ) { return NULL; } #endif size_t string_len = strlen( (const char *)file_dir ); int i; for ( i=(int)string_len-1; i>0; i-- ) { if ( GNB_FILE_SP==file_dir[i] ) { file_dir[i]='\0'; break; } } return file_dir; } char *gnb_get_file_dir_dup(char *file_name) { char *string = strdup(file_name); char *resolved_path = (char *)malloc(PATH_MAX); int i; size_t string_len = strlen( (const char *)string ); for ( i=(int)string_len-1; i>0; i-- ) { if ( '/'==string[i] || '\\'==string[i] ) { string[i]='\0'; break; } } #if __UNIX_LIKE_OS__ if ( NULL == realpath(string,resolved_path) ) { free(string); free(resolved_path); return NULL; } free(string); return resolved_path; #endif #ifdef _WIN32 if ( NULL == _fullpath(resolved_path, string, PATH_MAX) ) { free(string); free(resolved_path); return NULL; } free(string); return resolved_path; #endif } char *gnb_realpath(char *in_path, char *resolved_path) { int ret; size_t len; char *path; struct stat st; char *file_basename = NULL; char file_dir[PATH_MAX+NAME_MAX]; int i; ret = stat(in_path,&st); if ( 0 == ret && S_ISDIR(st.st_mode) ) { #if __UNIX_LIKE_OS__ if ( NULL == realpath(in_path,resolved_path) ) { return NULL; } else { return resolved_path; } #endif #ifdef _WIN32 if ( NULL == _fullpath(resolved_path, in_path, PATH_MAX) ) { return NULL; } else { return resolved_path; } #endif } len = strlen(in_path); for ( i=(int)len-1; i>=0; i-- ) { if ( GNB_FILE_SP == in_path[i] ) { file_basename = (char*)(in_path+i+1); break; } } if ( NULL == file_basename ) { return NULL; } len = strlen(file_basename); if ( len > NAME_MAX ) { return NULL; } strncpy(file_dir, in_path, PATH_MAX+NAME_MAX); len = strlen(file_dir); path = gnb_file_path_cut(file_dir, len); #if __UNIX_LIKE_OS__ if ( NULL == realpath(path,resolved_path) ) { return NULL; } #endif #ifdef _WIN32 if ( NULL == _fullpath(resolved_path, path, PATH_MAX) ) { return NULL; } #endif len = strlen(resolved_path); resolved_path[len] = GNB_FILE_SP; resolved_path[len+1] = '\0'; len++; for ( i=0; i= *lst_len_ptr ) { break; } if ( 0==strncmp(sub_dirent->d_name,".",GNB_MAX_FILE_NAME_LEN) ) { continue; } if ( 0==strncmp(sub_dirent->d_name,"..",GNB_MAX_FILE_NAME_LEN) ) { continue; } #if __UNIX_LIKE_OS__ if ( '/' == path[path_len-1] || '\\' == path[path_len-1] ) { snprintf(abs_filename, GNB_MAX_FILE_NAME_LEN, "%s%s", path, sub_dirent->d_name); } else { snprintf(abs_filename, GNB_MAX_FILE_NAME_LEN, "%s/%s", path, sub_dirent->d_name); } ret = lstat(abs_filename,&s); #endif #ifdef _WIN32 if ( '/' == path[path_len-1] || '\\' == path[path_len-1] ) { snprintf(abs_filename, GNB_MAX_FILE_NAME_LEN, "%s%s", path, sub_dirent->d_name); } else { snprintf(abs_filename, GNB_MAX_FILE_NAME_LEN, "%s\\%s", path, sub_dirent->d_name); } ret = stat(abs_filename,&s); #endif if ( -1==ret ) { continue; } if ( S_ISREG(s.st_mode) ) { file_type = GNB_FILE_TYPE_REG; } else if ( S_ISDIR(s.st_mode) ) { file_type = GNB_FILE_TYPE_DIR; #if __UNIX_LIKE_OS__ } else if (S_ISLNK(s.st_mode)) { file_type = GNB_FILE_TYPE_LNK; #endif } else { file_type = GNB_FILE_TYPE_INIT; } if ( GNB_FILE_TYPE_REG != file_type && GNB_FILE_TYPE_DIR != file_type ) { continue; } sub_file_info_lst[idx] = (gnb_file_info_t *)malloc(sizeof(gnb_file_info_t)); filename_len = strlen(sub_dirent->d_name) + 1; abs_filename_len = strlen(path) + filename_len + 1; sub_file_info_lst[idx]->name = (char *)malloc(filename_len); snprintf(sub_file_info_lst[idx]->name, filename_len, "%s", sub_dirent->d_name); sub_file_info_lst[idx]->abs_name = (char *)malloc(abs_filename_len); snprintf(sub_file_info_lst[idx]->abs_name, abs_filename_len, "%s", abs_filename); sub_file_info_lst[idx]->type = file_type; if ( idx >= *lst_len_ptr ) { break; } idx++; } closedir(dir); *lst_len_ptr = idx; return 0; } int gnb_scan_dir(char *path, gnb_file_info_t **file_info_lst, uint32_t *lst_len_ptr) { gnb_file_info_t **sub_file_info_lst = file_info_lst; int max_lst_len = *lst_len_ptr; uint32_t sub_lst_len = max_lst_len; int lst_len = 0; int i; gnb_get_dir_file_names(path, sub_file_info_lst, &sub_lst_len); lst_len += sub_lst_len; sub_file_info_lst += sub_lst_len; sub_lst_len = max_lst_len - lst_len; for ( i=0; itype ) { continue; } gnb_get_dir_file_names(file_info_lst[i]->abs_name, sub_file_info_lst, &sub_lst_len); if ( (lst_len+sub_lst_len) >= max_lst_len ) { break; } lst_len += sub_lst_len; sub_file_info_lst += sub_lst_len; sub_lst_len = max_lst_len - lst_len; } *lst_len_ptr = lst_len; return 0; } char *gnb_file_path_cut(char *filename, size_t len) { int i; if ( 0==len ) { return NULL; } for ( i=(int)len-1; i>=0; i-- ) { if ( GNB_FILE_SP == filename[i] ) { filename[i]='\0'; return filename; } } return NULL; } char *gnb_file_path_dup(const char *filename, size_t len) { int i; if ( 0==len ) { return NULL; } char *path_dup=strdup(filename); for ( i=(int)len-1; i>=0; i-- ) { if ( GNB_FILE_SP == path_dup[i] ) { path_dup[i]='\0'; return path_dup; } } free(path_dup); return NULL; } int gnb_mkdirs(char *path,mode_t mode) { char *dir_token_array[GNB_MAX_DIR_TOKEN_ARRAY_SIZE]; char path_buffer[PATH_MAX]; char token[PATH_MAX]; char *p; int i = 0; int dir_idx = 0; uint16_t buffer_off_set = 0; uint16_t buffer_len = PATH_MAX; struct stat s; int r; memset(dir_token_array, 0, GNB_MAX_DIR_TOKEN_ARRAY_SIZE); strncpy(path_buffer, path, PATH_MAX); p = path_buffer; while (*p) { if ( '/' == *p || '\\' == *p ) { if ( 0 != i ) { //找到子目录尾部 token[i] = '\0'; i = 0; dir_token_array[dir_idx] = strdup(token); dir_idx++; } } else { token[i] = *p; i++; } p++; } if ( 0 != i ) { token[i] = '\0'; dir_token_array[dir_idx] = strdup(token); dir_idx++; } //检查合法性 for (i=0;itype ) { r = remove(sub_dir_file_info_lst[i]->abs_name); if (r) { return -1; } } }while(i--); r = gnb_scan_dir(path, sub_dir_file_info_lst, &sub_dir_lst_len); if (0 != r ) { return -1; } i=sub_dir_lst_len-1; do{ if ( GNB_FILE_TYPE_DIR == sub_dir_file_info_lst[i]->type ) { r = remove(sub_dir_file_info_lst[i]->abs_name); if (r) { return -1; } } }while(i--); r = remove(path); if (r) { return -1; } return 0; } int gnb_inspect_in_directory(char *dst, char *src) { char *dir_token_array[GNB_MAX_DIR_TOKEN_ARRAY_SIZE]; char path_buffer[PATH_MAX]; char token[PATH_MAX]; char *p; int i = 0; int dir_idx = 0; char dst_realpath[PATH_MAX]; struct stat s; int r; if ( NULL == gnb_realpath(dst, dst_realpath) ) { return -1; } //检查 dst_realpath 是否为目录 r = stat(dst_realpath,&s); if ( 0 != r ) { return -1; } if ( !S_ISDIR(s.st_mode) ) { return -1; } memset(dir_token_array, 0, GNB_MAX_DIR_TOKEN_ARRAY_SIZE); strncpy(path_buffer, src, PATH_MAX); p = path_buffer; while (*p) { if ( '/' == *p || '\\' == *p ) { if ( 0 != i ) { //找到子目录尾部 token[i] = '\0'; i = 0; dir_token_array[dir_idx] = strdup(token); dir_idx++; } } else { token[i] = *p; i++; } p++; } if ( 0 != i ) { token[i] = '\0'; dir_token_array[dir_idx] = strdup(token); dir_idx++; } //检查合法性 for ( i=0; iname); free(file_info_lst[i]->abs_name); free(file_info_lst[i]); } free(file_info_lst); } opengnb-ver1.6.0.a/src/gnb_dir.h000077500000000000000000000043311500454252100164500ustar00rootroot00000000000000/* Copyright (C) 2019 gnbdev 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 . */ #ifndef GNB_DIR_H #define GNB_DIR_H #include #include char *gnb_get_file_dir(char *file_name, char *file_dir); char *gnb_get_file_dir_dup(char *file_name); char *gnb_realpath_dup(char *path); char *gnb_make_realpath_dup(char *base_path, char *sub_path); #define GNB_MAX_FILE_NAME_LEN 1024 #define GNB_MAX_DIR_TOKEN_ARRAY_SIZE 1024 typedef struct _gnb_file_info_t{ char *name; //绝对路径 char *abs_name; #define GNB_FILE_TYPE_INIT 0 #define GNB_FILE_TYPE_REG 1 #define GNB_FILE_TYPE_DIR 2 #define GNB_FILE_TYPE_LNK 3 uint8_t type; }gnb_file_info_t; int gnb_get_dir_file_names(char *path, gnb_file_info_t **sub_file_info_lst, uint32_t *lst_len_ptr); /* 遍历目录下所有的目录和文件,文件/目录的数量 由 *lst_len_ptr 限制 */ int gnb_scan_dir(char *path, gnb_file_info_t **file_info_lst, uint32_t *lst_len_ptr); char *gnb_file_path_cut(char *filename, size_t len); char *gnb_file_path_dup(const char *filename, size_t len); /* 从传入的文件路径中得到文件的目录和文件名,通过 realpath(Unix 平台) 或 _fullpath (Windows平台) 获得文件目录的绝对路径,与文件名合并成一个字符串返回 */ char *gnb_realpath(char *in_path, char *resolved_path); int gnb_mkdirs(char *path,mode_t mode); int gnb_remove_dirs(char *path); void gnb_release_file_info_lst(gnb_file_info_t **file_info_lst, int lst_len); int gnb_mkdirs(char *path,mode_t mode); /*检查一个src文件或目录,是否在dst目录下,dst 必须是存在的目录*/ int gnb_inspect_in_directory(char *dst, char *src); #endif opengnb-ver1.6.0.a/src/gnb_discover_in_lan_frame_type.h000077500000000000000000000030271500454252100232440ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 . */ #ifndef GNB_DISCOVER_IN_LAN_FRAME_TYPE_H #define GNB_DISCOVER_IN_LAN_FRAME_TYPE_H #include "stdint.h" #include "gnb_core_frame_type_defs.h" #pragma pack(push, 1) typedef struct _discover_lan_in_frame_t { struct __attribute__((__packed__)) discover_lan_in_data { unsigned char arg0; unsigned char arg1; unsigned char arg2; unsigned char arg3; unsigned char src_key512[64]; gnb_uuid_t src_uuid64; uint8_t src_addr6_a[16]; uint16_t src_port6_a; uint8_t src_addr4[4]; uint16_t src_port4; uint64_t src_ts_usec; char text[256]; char attachment[128]; }data; unsigned char src_sign[ED25519_SIGN_SIZE]; }__attribute__ ((__packed__)) discover_lan_in_frame_t; #pragma pack(pop) #define PAYLOAD_DISCOVER_LAN_IN_FRAME_PAYLOAD_SIZE (sizeof(gnb_payload16_t) + sizeof(discover_lan_in_frame_t)) #endif opengnb-ver1.6.0.a/src/gnb_doubly_linked_list.c000077500000000000000000000144471500454252100215550ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 #include #include "gnb_doubly_linked_list.h" void gnb_doubly_linked_list_node_set(gnb_doubly_linked_list_node_t *doubly_linked_list_node,void *data){ doubly_linked_list_node->data = data; } gnb_doubly_linked_list_t* gnb_doubly_linked_list_create(gnb_heap_t *heap){ gnb_doubly_linked_list_t *doubly_linked_list = (gnb_doubly_linked_list_t *)gnb_heap_alloc(heap,sizeof(gnb_doubly_linked_list_t)); memset(doubly_linked_list,0,sizeof(gnb_doubly_linked_list_t)); doubly_linked_list->heap = heap; return doubly_linked_list; } void gnb_doubly_linked_list_release(gnb_doubly_linked_list_t *doubly_linked_list){ gnb_heap_free(doubly_linked_list->heap,doubly_linked_list); } int gnb_doubly_linked_list_add(gnb_doubly_linked_list_t *doubly_linked_list, gnb_doubly_linked_list_node_t *dl_node){ if ( 0==doubly_linked_list->num ) { doubly_linked_list->head = dl_node; dl_node->pre = NULL; dl_node->nex = NULL; doubly_linked_list->tail = dl_node; goto finish; } if ( 1==doubly_linked_list->num ) { dl_node->pre = NULL; dl_node->nex = doubly_linked_list->head; doubly_linked_list->head->pre = dl_node; doubly_linked_list->tail = doubly_linked_list->head; doubly_linked_list->head = dl_node; goto finish; } dl_node->pre = NULL; dl_node->nex = doubly_linked_list->head; doubly_linked_list->head->pre = dl_node; doubly_linked_list->head = dl_node; finish: doubly_linked_list->num++; return 0; } gnb_doubly_linked_list_node_t* gnb_doubly_linked_list_pop_head(gnb_doubly_linked_list_t *doubly_linked_list){ gnb_doubly_linked_list_node_t *dl_node; if ( 0 == doubly_linked_list->num ) { return NULL; } if ( 1 == doubly_linked_list->num ) { if ( doubly_linked_list->head != doubly_linked_list->tail ) { return NULL; } dl_node = doubly_linked_list->head; doubly_linked_list->head = NULL; doubly_linked_list->tail = NULL; doubly_linked_list->num = 0; return dl_node; } if ( doubly_linked_list->head == doubly_linked_list->tail ) { return NULL; } dl_node = doubly_linked_list->head; doubly_linked_list->head = dl_node->nex; doubly_linked_list->head->pre = NULL; doubly_linked_list->num--; return dl_node; } gnb_doubly_linked_list_node_t* gnb_doubly_linked_list_pop_tail(gnb_doubly_linked_list_t *doubly_linked_list){ gnb_doubly_linked_list_node_t *dl_node; if ( 0 == doubly_linked_list->num ) { return NULL; } if ( 1 == doubly_linked_list->num ) { if ( doubly_linked_list->head != doubly_linked_list->tail ) { return NULL; } dl_node = doubly_linked_list->tail; doubly_linked_list->head = NULL; doubly_linked_list->tail = NULL; doubly_linked_list->num = 0; return dl_node; } if ( doubly_linked_list->head == doubly_linked_list->tail ) { return NULL; } dl_node = doubly_linked_list->tail; doubly_linked_list->tail = dl_node->pre; doubly_linked_list->tail->nex = NULL; doubly_linked_list->num--; return dl_node; } int gnb_doubly_linked_list_move_head(gnb_doubly_linked_list_t *doubly_linked_list, gnb_doubly_linked_list_node_t *dl_node){ if ( 1==doubly_linked_list->num || 2==doubly_linked_list->num ) { return 0; } gnb_doubly_linked_list_node_t *pre_node = dl_node->pre; gnb_doubly_linked_list_node_t *nex_node = dl_node->nex; if( NULL == pre_node ) { //is header return 0; } if ( NULL != nex_node ) { nex_node->pre = pre_node; } else { doubly_linked_list->tail = pre_node; } pre_node->nex = nex_node; dl_node->nex = doubly_linked_list->head; doubly_linked_list->head->pre = dl_node; doubly_linked_list->head = dl_node; dl_node->pre = NULL; return 0; } int gnb_doubly_linked_list_pop(gnb_doubly_linked_list_t *doubly_linked_list, gnb_doubly_linked_list_node_t *dl_node){ if ( 0==doubly_linked_list->num ) { return 0; } gnb_doubly_linked_list_node_t *pre_node = dl_node->pre; gnb_doubly_linked_list_node_t *nex_node = dl_node->nex; if ( NULL == pre_node && NULL == nex_node ) { if ( doubly_linked_list->head != dl_node ) { return -1; } if ( doubly_linked_list->tail != dl_node ) { return -1; } if ( 1 != doubly_linked_list->num ) { return -1; } doubly_linked_list->head = NULL; doubly_linked_list->tail = NULL; doubly_linked_list->num = 0; return 0; } if ( NULL == pre_node ) { //is header if ( doubly_linked_list->head != dl_node ) { return -1; } if ( 1 == doubly_linked_list->num ) { return -1; } nex_node->pre = NULL; doubly_linked_list->head = nex_node; doubly_linked_list->num--; return 0; } if ( NULL==nex_node ) { //is tail if ( doubly_linked_list->tail != dl_node ) { return -1; } if ( 1 == doubly_linked_list->num ) { return -1; } pre_node->nex = NULL; doubly_linked_list->tail = pre_node; doubly_linked_list->num--; return 0; } pre_node->nex = nex_node; nex_node->pre = pre_node; doubly_linked_list->num--; return 0; } opengnb-ver1.6.0.a/src/gnb_doubly_linked_list.h000077500000000000000000000042151500454252100215520ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 . */ #ifndef GNB_DOUBLY_LINKED_LIST_H #define GNB_DOUBLY_LINKED_LIST_H #include #include "gnb_alloc.h" typedef struct _gnb_doubly_linked_list_node_t gnb_doubly_linked_list_node_t; typedef struct _gnb_doubly_linked_list_t gnb_doubly_linked_list_t; typedef struct _gnb_doubly_linked_list_node_t{ gnb_doubly_linked_list_node_t *pre; gnb_doubly_linked_list_node_t *nex; void *data; }gnb_doubly_linked_list_node_t; typedef struct _gnb_doubly_linked_list_t{ gnb_heap_t *heap; gnb_doubly_linked_list_node_t *head; gnb_doubly_linked_list_node_t *tail; uint32_t num; }gnb_doubly_linked_list_t; void gnb_doubly_linked_list_node_set(gnb_doubly_linked_list_node_t *dl_node,void *data); gnb_doubly_linked_list_t* gnb_doubly_linked_list_create(gnb_heap_t *heap); void gnb_doubly_linked_list_release(gnb_doubly_linked_list_t *doubly_linked_list); int gnb_doubly_linked_list_add(gnb_doubly_linked_list_t *doubly_linked_list, gnb_doubly_linked_list_node_t *dl_node); gnb_doubly_linked_list_node_t* gnb_doubly_linked_list_pop_head(gnb_doubly_linked_list_t *doubly_linked_list); gnb_doubly_linked_list_node_t* gnb_doubly_linked_list_pop_tail(gnb_doubly_linked_list_t *doubly_linked_list); int gnb_doubly_linked_list_pop(gnb_doubly_linked_list_t *doubly_linked_list, gnb_doubly_linked_list_node_t *dl_node); int gnb_doubly_linked_list_move_head(gnb_doubly_linked_list_t *doubly_linked_list, gnb_doubly_linked_list_node_t *dl_node); #endif opengnb-ver1.6.0.a/src/gnb_exec.h000077500000000000000000000024241500454252100166170ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 . */ #ifndef GNB_EXEC_H #define GNB_EXEC_H #include "gnb_platform.h" #include "gnb_arg_list.h" #define GNB_EXEC_FOREGROUND (0x1) #define GNB_EXEC_BACKGROUND (0x1 << 1) #define GNB_EXEC_WAIT (0x1 << 2) #ifdef __UNIX_LIKE_OS__ #include #include pid_t gnb_exec(char *app_filename, char *current_path, gnb_arg_list_t *arg_list, int flag); void gnb_kill(pid_t pid); #endif #ifdef _WIN32 #ifndef NAME_MAX #define NAME_MAX 255 #endif #include int gnb_exec(char *app_filename, char *current_path, gnb_arg_list_t *gnb_arg_list, int flag); int gnb_kill(DWORD pid); #endif #endif opengnb-ver1.6.0.a/src/gnb_fixed_pool.c000077500000000000000000000044421500454252100200200ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 #include #include "gnb_fixed_pool.h" typedef struct _gnb_fixed_pool_t{ uint32_t num; uint32_t bsize; void *block; uint32_t array_len; void *array[0]; }gnb_fixed_pool_t; gnb_fixed_pool_t* gnb_fixed_pool_create(gnb_heap_t *heap, uint32_t array_len, uint32_t bsize){ gnb_fixed_pool_t *fixed_pool; fixed_pool = (gnb_fixed_pool_t *)gnb_heap_alloc(heap, sizeof(gnb_fixed_pool_t) + sizeof(void *) * array_len ); fixed_pool->num = array_len; fixed_pool->bsize = bsize; fixed_pool->block = gnb_heap_alloc(heap,bsize * array_len); memset(fixed_pool->block, 0, bsize * array_len); fixed_pool->array_len = array_len; int i; void *p; p = fixed_pool->block; for ( i=0; iarray[i] = p; p += bsize; } return fixed_pool; } void* gnb_fixed_pool_pop(gnb_fixed_pool_t *fixed_pool){ if ( 0 == fixed_pool->num ) { return NULL; } void *block; block = fixed_pool->array[fixed_pool->num-1]; fixed_pool->array[fixed_pool->num-1] = NULL; fixed_pool->num--; return block; } uint32_t gnb_fixed_pool_push(gnb_fixed_pool_t *fixed_pool, void *block){ if ( fixed_pool->array_len == fixed_pool->num ) { return 0; } if ( NULL != fixed_pool->array[fixed_pool->num] ) { return -1; } fixed_pool->array[fixed_pool->num] = block; fixed_pool->num++; return fixed_pool->num; } void gnb_fixed_pool_release(gnb_heap_t *heap,gnb_fixed_pool_t *fixed_pool){ gnb_heap_free(heap, fixed_pool->block); gnb_heap_free(heap, fixed_pool); } opengnb-ver1.6.0.a/src/gnb_fixed_pool.h000077500000000000000000000021551500454252100200240ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 . */ #ifndef GNB_FIXED_POOL_H #define GNB_FIXED_POOL_H #include #include "gnb_alloc.h" typedef struct _gnb_fixed_pool_t gnb_fixed_pool_t; gnb_fixed_pool_t* gnb_fixed_pool_create(gnb_heap_t *heap, uint32_t array_len, uint32_t bsize); void* gnb_fixed_pool_pop(gnb_fixed_pool_t *fixed_pool); uint32_t gnb_fixed_pool_push(gnb_fixed_pool_t *fixed_pool, void *block); void gnb_fixed_pool_release(gnb_heap_t *heap,gnb_fixed_pool_t *fixed_pool); #endif opengnb-ver1.6.0.a/src/gnb_hash32.c000077500000000000000000000274101500454252100167600ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 #include #include "gnb_hash32.h" typedef struct _gnb_hash32_bucket_t{ uint32_t chain_len; gnb_kv32_t *kv_chain; }gnb_hash32_bucket_t; uint32_t murmurhash_hash(unsigned char *data, size_t len); gnb_hash32_map_t *gnb_hash32_create(gnb_heap_t *heap, uint32_t bucket_num, uint32_t kv_num){ gnb_hash32_map_t *hash32_map = gnb_heap_alloc(heap, sizeof(gnb_hash32_map_t)); if ( NULL == hash32_map ) { return NULL; } memset(hash32_map, 0, sizeof(gnb_hash32_map_t)); hash32_map->heap = heap; hash32_map->buckets = gnb_heap_alloc(hash32_map->heap, sizeof(gnb_hash32_bucket_t *) * bucket_num ); if ( NULL == hash32_map->buckets ) { return NULL; } hash32_map->bucket_num = bucket_num; uint32_t i; void *p = gnb_heap_alloc(hash32_map->heap, sizeof(gnb_hash32_bucket_t)*bucket_num ); if ( NULL == p ) { return NULL; } memset(p, 0, sizeof(gnb_hash32_bucket_t)*bucket_num); for ( i=0; ibuckets[i] = p; p += sizeof(gnb_hash32_bucket_t); } return hash32_map; } void gnb_hash32_release(gnb_hash32_map_t *hash32_map){ gnb_heap_free(hash32_map->heap, hash32_map); } gnb_kv32_t *gnb_kv32_create(gnb_hash32_map_t *hash32_map, u_char *key, uint32_t key_len, u_char *value, uint32_t value_len){ uint32_t r_key_len; uint32_t r_value_len; if ( 0 != key_len ) { r_key_len = key_len; } else { r_key_len = sizeof(void *); } if ( 0 != value_len ) { r_value_len = value_len; } else { r_value_len = sizeof(void *); } gnb_kv32_t *kv = gnb_heap_alloc(hash32_map->heap, sizeof(gnb_kv32_t) + sizeof(gnb_block32_t) + r_key_len + sizeof(gnb_block32_t) + r_value_len ); if ( NULL == kv ) { return NULL; } void *p = (void *)kv; kv->key = p + sizeof(gnb_kv32_t); kv->value = p + sizeof(gnb_kv32_t) + sizeof(gnb_block32_t) + key_len; kv->nex = NULL; memcpy(kv->key->data, key, key_len); kv->key->size = key_len; if ( 0 != value_len ) { memcpy(kv->value->data, value, value_len); kv->value->size = value_len; } else { //直接存 void* GNB_BLOCK_VOID(kv->value) = value; kv->value->size = 0; } return kv; } void gnb_kv32_release(gnb_hash32_map_t *hash_map, gnb_kv32_t *kv){ gnb_heap_free(hash_map->heap, kv); } gnb_kv32_t *gnb_hash32_set(gnb_hash32_map_t *hash32_map, u_char *key, uint32_t key_len, void *value, uint32_t value_len){ gnb_kv32_t *kv = NULL; uint32_t hashcode = murmurhash_hash(key, key_len); uint32_t bucket_idx = hashcode % hash32_map->bucket_num; gnb_hash32_bucket_t *bucket = hash32_map->buckets[bucket_idx]; if ( NULL == bucket->kv_chain ) { bucket->kv_chain = gnb_kv32_create(hash32_map, key, key_len, value, value_len); bucket->kv_chain->nex = NULL; bucket->chain_len = 1; hash32_map->kv_num++; goto finish; } gnb_kv32_t *kv_chain = bucket->kv_chain; gnb_kv32_t *pre_kv_chain = kv_chain; do{ if ( key_len != kv_chain->key->size ) { pre_kv_chain = kv_chain; kv_chain = kv_chain->nex; continue; } if ( !memcmp(kv_chain->key->data, key, key_len) ) { kv = kv_chain; if ( 0 != value_len ) { memcpy(kv->value->data, value, value_len); kv->value->size = value_len; } else { //直接存 void* GNB_BLOCK_VOID(kv->value) = value; kv->value->size = 0; } break; } pre_kv_chain = kv_chain; kv_chain = kv_chain->nex; }while (kv_chain); if ( NULL == kv ) { pre_kv_chain->nex = gnb_kv32_create(hash32_map, key, key_len, value, value_len); bucket->chain_len++; hash32_map->kv_num++; goto finish; } finish: return kv; } int gnb_hash32_store(gnb_hash32_map_t *hash32_map, u_char *key, uint32_t key_len, void *value, uint32_t value_len){ gnb_kv32_t *kv = NULL; uint32_t hashcode = murmurhash_hash(key, key_len); uint32_t bucket_idx = hashcode % hash32_map->bucket_num; gnb_hash32_bucket_t *bucket = hash32_map->buckets[bucket_idx]; if ( NULL == bucket->kv_chain ) { bucket->kv_chain = gnb_kv32_create(hash32_map, key, key_len, value, value_len); bucket->chain_len = 1; hash32_map->kv_num++; goto finish; } gnb_kv32_t *kv_chain = bucket->kv_chain; gnb_kv32_t *pre_kv_chain = kv_chain; do{ if ( key_len != kv_chain->key->size ) { pre_kv_chain = kv_chain; kv_chain = kv_chain->nex; continue; } if ( !memcmp(kv_chain->key->data, key, key_len) ) { gnb_kv32_release(hash32_map, kv_chain); if ( bucket->kv_chain != kv_chain ) { pre_kv_chain->nex = gnb_kv32_create(hash32_map, key, key_len, value, value_len); } else { bucket->kv_chain = gnb_kv32_create(hash32_map, key, key_len, value, value_len); } break; } pre_kv_chain = kv_chain; kv_chain = kv_chain->nex; }while (kv_chain); if ( NULL == kv ) { pre_kv_chain->nex = gnb_kv32_create(hash32_map, key, key_len, value, value_len); bucket->chain_len++; hash32_map->kv_num++; goto finish; } finish: return 0; } gnb_kv32_t *gnb_hash32_get(gnb_hash32_map_t *hash32_map, u_char *key, uint32_t key_len){ gnb_kv32_t *kv = NULL; uint32_t hashcode = murmurhash_hash(key, key_len); uint32_t bucket_idx = hashcode % hash32_map->bucket_num; gnb_hash32_bucket_t *bucket = hash32_map->buckets[bucket_idx]; if ( NULL == bucket->kv_chain ) { goto finish; } gnb_kv32_t *kv_chain = bucket->kv_chain; do{ if ( key_len != kv_chain->key->size ) { kv_chain = kv_chain->nex; continue; } if ( !memcmp(kv_chain->key->data, key, key_len) ) { kv = kv_chain; break; } kv_chain = kv_chain->nex; }while (kv_chain); finish: return kv; } gnb_kv32_t *gnb_hash32_del(gnb_hash32_map_t *hash32_map, u_char *key, uint32_t key_len){ gnb_kv32_t *old_kv = NULL; uint32_t hashcode = murmurhash_hash(key, key_len); uint32_t bucket_idx = hashcode % hash32_map->bucket_num; gnb_hash32_bucket_t *bucket = hash32_map->buckets[bucket_idx]; if ( NULL == bucket->kv_chain ) { goto finish; } gnb_kv32_t *kv_chain = bucket->kv_chain; if ( !memcmp(kv_chain->key->data, key, key_len) ) { old_kv = kv_chain; hash32_map->kv_num--; if ( 1 == bucket->chain_len ) { bucket->kv_chain = NULL; bucket->chain_len = 0; } else { bucket->kv_chain = kv_chain->nex; bucket->chain_len--; } goto finish; } gnb_kv32_t *pre_kv_chain = kv_chain; kv_chain = kv_chain->nex; if ( NULL == kv_chain ) { goto finish; } do{ if ( key_len != kv_chain->key->size ) { pre_kv_chain = kv_chain; kv_chain = kv_chain->nex; continue; } if ( !memcmp(kv_chain->key->data, key, key_len) ) { pre_kv_chain->nex = kv_chain->nex; old_kv = kv_chain; bucket->chain_len--; hash32_map->kv_num--; break; } pre_kv_chain = kv_chain; kv_chain = kv_chain->nex; }while (kv_chain); finish: return old_kv; } gnb_kv32_t **gnb_hash32_array(gnb_hash32_map_t *hash32_map, uint32_t *num){ gnb_kv32_t *kv; gnb_kv32_t ** kv_array = NULL; gnb_hash32_bucket_t *bucket; if ( 0 == hash32_map->kv_num ) { *num = 0; return NULL; } if ( hash32_map->kv_num < (*num) ) { *num = hash32_map->kv_num; } kv_array = gnb_heap_alloc(hash32_map->heap, sizeof(gnb_kv32_t *) * (*num) ); uint32_t i,j; uint32_t idx = 0; for (i=0; ibucket_num; i++) { bucket = hash32_map->buckets[i]; if ( 0 == bucket->chain_len ) { continue; } kv = bucket->kv_chain; for (j=0; jchain_len; j++) { kv_array[idx] = kv; idx++; kv = kv->nex; } } return kv_array; } uint32_t* gnb_hash32_uint32_keys(gnb_hash32_map_t *hash32_map, uint32_t *num){ gnb_kv32_t *kv; uint32_t *uint32_array = NULL; gnb_hash32_bucket_t *bucket; if ( 0 == hash32_map->kv_num ) { *num = 0; return NULL; } if ( hash32_map->kv_num < (*num) ) { *num = hash32_map->kv_num; } uint32_array = gnb_heap_alloc(hash32_map->heap, sizeof(uint32_t) * (*num) ); uint32_t i,j; uint32_t idx = 0; for (i=0; ibucket_num; i++) { bucket = hash32_map->buckets[i]; if ( 0 == bucket->chain_len ) { continue; } kv = bucket->kv_chain; for (j=0; jchain_len; j++) { uint32_array[idx] = GNB_HASH32_UINT32_KEY(kv); idx++; kv = kv->nex; } } return uint32_array; } uint64_t* gnb_hash32_uint64_keys(gnb_hash32_map_t *hash32_map, uint32_t *num){ gnb_kv32_t *kv; uint64_t *uint64_array = NULL; gnb_hash32_bucket_t *bucket; if ( 0 == hash32_map->kv_num ) { *num = 0; return NULL; } if ( hash32_map->kv_num < (*num) ) { *num = hash32_map->kv_num; } uint64_array = gnb_heap_alloc(hash32_map->heap, sizeof(uint64_t) * (*num) ); uint32_t i,j; uint32_t idx = 0; for (i=0; ibucket_num; i++) { bucket = hash32_map->buckets[i]; if ( 0 == bucket->chain_len ) { continue; } kv = bucket->kv_chain; for (j=0; jchain_len; j++) { uint64_array[idx] = GNB_HASH32_UINT64_KEY(kv); idx++; kv = kv->nex; } } return uint64_array; } u_char** gnb_hash32_string_keys(gnb_hash32_map_t *hash32_map, uint32_t *num){ gnb_kv32_t *kv; u_char** string_array = NULL; gnb_hash32_bucket_t *bucket; if ( 0 == hash32_map->kv_num ) { *num = 0; return NULL; } if ( hash32_map->kv_num < (*num) ) { *num = hash32_map->kv_num; } string_array = gnb_heap_alloc(hash32_map->heap, sizeof(u_char*) * (*num) ); uint32_t i,j; uint32_t idx = 0; for (i=0; ibucket_num; i++) { bucket = hash32_map->buckets[i]; if ( 0 == bucket->chain_len ) { continue; } kv = bucket->kv_chain; for (j=0; jchain_len; j++) { string_array[idx] = GNB_HASH32_STRING_KEY(kv); idx++; kv = kv->nex; } } return string_array; } opengnb-ver1.6.0.a/src/gnb_hash32.h000077500000000000000000000122441500454252100167640ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 . */ #ifndef GNB_HASH32_H #define GNB_HASH32_H #include #include #ifndef __u_char_defined typedef unsigned char u_char; #define __u_char_defined #endif #include "gnb_alloc.h" #include "gnb_block.h" typedef struct _gnb_kv32_t gnb_kv32_t; typedef struct _gnb_kv32_t{ gnb_block32_t *key; gnb_block32_t *value; gnb_kv32_t *nex; }gnb_kv32_t; typedef struct _gnb_hash32_bucket_t gnb_hash32_bucket_t; typedef struct _gnb_hash32_map_t{ gnb_heap_t *heap; uint32_t bucket_num; uint32_t kv_num; gnb_hash32_bucket_t **buckets; } gnb_hash32_map_t; gnb_hash32_map_t *gnb_hash32_create(gnb_heap_t *heap, uint32_t bucket_num,uint32_t kv_num); void gnb_hash32_release(gnb_hash32_map_t *hash32_map); gnb_kv32_t* gnb_hash32_set(gnb_hash32_map_t *hash32_map, u_char *key, uint32_t key_len, void *value, uint32_t value_len); int gnb_hash32_store(gnb_hash32_map_t *hash32_map, u_char *key, uint32_t key_len, void *value, uint32_t value_len); gnb_kv32_t* gnb_hash32_get(gnb_hash32_map_t *hash32_map, u_char *key, uint32_t key_len); gnb_kv32_t* gnb_hash32_del(gnb_hash32_map_t *hash32_map, u_char *key, uint32_t key_len); void gnb_kv32_release(gnb_hash32_map_t *hash_map, gnb_kv32_t *kv); gnb_kv32_t** gnb_hash32_array(gnb_hash32_map_t *hash32_map, uint32_t *num); #define GNB_HASH32_UINT32_SET(hash32_map,uint32key,value) gnb_hash32_set(hash32_map,(u_char *)&uint32key,sizeof(uint32_t),value,0) #define GNB_HASH32_UINT32_STORE(hash32_map,uint32key,value,value_len) gnb_hash32_store(hash32_map,(u_char *)&uint32key,sizeof(uint32_t),value,value_len) #define GNB_HASH32_UINT32_GET(hash32_map,uint32key) gnb_hash32_get(hash32_map,(u_char *)&uint32key,sizeof(uint32_t)) #define GNB_HASH32_UINT32_GET_PTR(hash32_map,uint32key) GNB_HASH32_VALUE_PTR(gnb_hash32_get(hash32_map,(u_char *)&uint32key,sizeof(uint32_t))) #define GNB_HASH32_UINT32_DEL(hash32_map,uint32key) gnb_hash32_del(hash32_map,(u_char *)&uint32key,sizeof(uint32_t)) uint32_t* gnb_hash32_uint32_keys(gnb_hash32_map_t *hash32_map, uint32_t *num); #define GNB_HASH32_UINT64_SET(hash32_map,uint64key,value) gnb_hash32_set(hash32_map,(u_char *)&uint64key,sizeof(uint64_t),value,0) #define GNB_HASH32_UINT64_STORE(hash32_map,uint64key,value,value_len) gnb_hash32_store(hash32_map,(u_char *)&uint64key,sizeof(uint64_t),value,value_len) #define GNB_HASH32_UINT64_GET(hash32_map,uint64key) gnb_hash32_get(hash32_map,(u_char *)&uint64key,sizeof(uint64_t)) #define GNB_HASH32_UINT64_GET_PTR(hash32_map,uint64key) GNB_HASH32_VALUE_PTR(gnb_hash32_get(hash32_map,(u_char *)&uint64key,sizeof(uint64_t))) #define GNB_HASH32_UINT64_DEL(hash32_map,uint64key) gnb_hash32_del(hash32_map,(u_char *)&uint64key,sizeof(uint64_t)) uint64_t* gnb_hash32_uint64_keys(gnb_hash32_map_t *hash32_map, uint32_t *num); #define GNB_HASH32_SET(hash32_map,string,string_len,value) gnb_hash32_set(hash32_map, string, (uint32_t)string_len, value, 0) #define GNB_HASH32_STORE(hash32_map,string,string_len,value,value_len) gnb_hash32_store(hash32_map,string,(uint32_t)string_len,value,(uint32_t)value_len) #define GNB_HASH32_GET(hash32_map,key_string,key_string_len) gnb_hash32_get(hash32_map,key_string,(uint32_t)key_string_len) #define GNB_HASH32_GET_PTR(hash32_map,key_string,key_string_len) GNB_HASH32_VALUE_PTR(gnb_hash32_get(hash32_map,key_string,(uint32_t)key_string_len)) #define GNB_HASH32_DEL(hash32_map,string,string_len) gnb_hash32_del(hash32_map,string,(uint32_t)string_len) u_char** gnb_hash32_string_keys(gnb_hash32_map_t *hash32_map, uint32_t *num); #define GNB_HASH32_UINT32_KEY(kv32) (*(uint32_t *)kv32->key->data) #define GNB_HASH32_UINT32_VALUE(kv32) (*(uint32_t *)kv32->value->data) #define GNB_HASH32_UINT64_KEY(kv32) (*(uint64_t *)kv32->key->data) #define GNB_HASH32_UINT64_VALUE(kv32) (*(uint64_t *)kv32->key->data) #define GNB_HASH32_STRING_KEY(kv32) ((unsigned char *)kv32->key->data) #define GNB_HASH32_STRING_VALUE(kv32) ((unsigned char *)kv32->value->data) #define GNB_HASH32_KEY_SIZE(kv32) (kv32->key->size) #define GNB_HASH32_VALUE_SIZE(kv32) (kv32->value->size) #define GNB_HASH32_KEY_PTR(kv32) kv32!=NULL?(*(void **)&kv32->key->data):NULL #define GNB_HASH32_VALUE_PTR(kv32) kv32!=NULL?(*(void **)&kv32->value->data):NULL #define GNB_HASH32_VALUE(kv32) kv32!=NULL?kv32->value:NULL #define GNB_HASH32_GET_VALUE(hash32_map,key,key_len) ( GNB_HASH32_VALUE( gnb_hash32_get(hash32_map,key,key_len) ) ) #define GNB_HASH32_UINT32_GET_VALUE(hash32_map,uint32key) ( GNB_HASH32_VALUE( gnb_hash32_get(hash32_map,(u_char *)&uint32key,sizeof(uint32_t)) ) ) #endif opengnb-ver1.6.0.a/src/gnb_index_frame_type.h000077500000000000000000000141731500454252100212210ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 . */ #ifndef GNB_INDEX_FRAME_TYPE_H #define GNB_INDEX_FRAME_TYPE_H #include "stdint.h" #include "gnb_core_frame_type_defs.h" //向 index node 提交地址时间间隔,默认为 60 秒 #define GNB_POST_ADDR_INTERVAL_TIME_SEC 60 //向 index 提交节点地址的频率限制 默认为 20秒 #define GNB_POST_ADDR_LIMIT_SEC 20 //向 index node 请求节点地址时间间隔,默认为 39 秒 #define GNB_REQUEST_ADDR_INTERVAL_SEC 39 //节点向index 节点请求地址的频率限制 默认为 20毫秒 #define GNB_REQUEST_ADDR_LIMIT_USEC 1000*20 #define INDEX_ATTACHMENT_SIZE (4+128) #pragma pack(push, 1) #define NODE_RANDOM_SEQUENCE_SIZE 32 #define GNB_KEY_ADDRESS_NUM 3 //node to index typedef struct _post_addr_frame_t { struct __attribute__((__packed__)) post_addr_frame_data { // arg0 = 'p' unsigned char arg0; //保留 //当 arg0='p', arg1='a' 或 arg1='b' 请求把 attachment 保存在 gnb_key_address_t 中的 attachmenta 或 attachmentb 里面 unsigned char arg1; unsigned char arg2; //保留 unsigned char arg3; //保留 unsigned char src_key512[64]; //发送节点的key gnb_uuid_t src_uuid64; //发送方的uuid64,可选 uint64_t src_ts_usec; //发送方的时间戳,可选 //源节点对自身探测的wan地址 uint8_t wan6_addr[16]; uint16_t wan6_port; uint8_t wan4_addr[4]; uint16_t wan4_port; /* 节点提交地址时生成一组随机数,然后对这组随机数进行数字签名 * index 节点会保存最后收到的 node_random_sequence,node_random_sequence_sign * PUSH ADDR 给到请求节点上,请求节点会用公钥检验这个签名, 这样包括 attachment 在内的数据都可以防止伪造 * */ unsigned char node_random_sequence[NODE_RANDOM_SEQUENCE_SIZE]; unsigned char node_random_sequence_sign[ED25519_SIGN_SIZE]; char text[32]; char attachment[INDEX_ATTACHMENT_SIZE]; }data; unsigned char src_sign[ED25519_SIGN_SIZE]; gnb_uuid_t node_uuid64; }__attribute__ ((__packed__)) post_addr_frame_t; //index to node typedef struct _echo_addr_frame_t { struct __attribute__((__packed__)) echo_addr_frame_data { unsigned char arg0; //保留 unsigned char arg1; //保留 unsigned char arg2; //保留 unsigned char arg3; //保留 unsigned char dst_key512[64]; //发送post addr节点的key gnb_uuid_t dst_uuid64; //发送post addr节点的uuid64 uint64_t src_ts_usec; //发送方的时间戳,可选 char addr_type; //ipv6='6' or ipv4='4' uint8_t addr[16]; uint16_t port; char text[80]; }data; unsigned char src_sign[ED25519_SIGN_SIZE]; gnb_uuid_t index_node_uuid64; }__attribute__ ((__packed__)) echo_addr_frame_t; //node to index typedef struct _request_addr_frame_t { struct __attribute__((__packed__)) request_addr_frame_data { // 'g' 获取 attachment unsigned char arg0; //当 arg0='g', arg1='a' 或 arg1='b' 请求获取保存在 gnb_key_address_t 中的 attachmenta 或 attachmentb unsigned char arg1; unsigned char arg2; //保留 unsigned char arg3; //保留 unsigned char src_key512[64]; //发送节点的key unsigned char dst_key512[64]; //被查询节点的key gnb_uuid_t src_uuid64; //发送方的uuid64,可选 gnb_uuid_t dst_uuid64; //被查询节点的uuid可选 uint64_t src_ts_usec; char text[32]; }data; unsigned char src_sign[ED25519_SIGN_SIZE]; gnb_uuid_t node_uuid64; }__attribute__ ((__packed__)) request_addr_frame_t; //index to node typedef struct _push_addr_frame_t { struct __attribute__((__packed__)) push_addr_frame_data { #define PUSH_ADDR_ACTION_NOTIFY 'N' #define PUSH_ADDR_ACTION_CONNECT 'C' unsigned char arg0; unsigned char arg1; unsigned char arg2; //保留 unsigned char arg3; //保留 unsigned char node_key[64]; gnb_uuid_t node_uuid64; uint8_t addr6_a[16]; uint16_t port6_a; uint8_t addr6_b[16]; uint16_t port6_b; uint8_t addr6_c[16]; uint16_t port6_c; uint8_t addr4_a[4]; uint16_t port4_a; uint8_t addr4_b[4]; uint16_t port4_b; uint8_t addr4_c[4]; uint16_t port4_c; unsigned char node_random_sequence[NODE_RANDOM_SEQUENCE_SIZE]; unsigned char node_random_sequence_sign[ED25519_SIGN_SIZE]; uint64_t src_ts_usec; uint64_t idx_ts_usec; char text[32]; char attachment[INDEX_ATTACHMENT_SIZE]; }data; gnb_uuid_t index_node_uuid64; unsigned char src_sign[ED25519_SIGN_SIZE]; }__attribute__ ((__packed__)) push_addr_frame_t; #define PUSH_ADDR_FRAME_PAYLOAD_SIZE (sizeof(gnb_payload16_t) + sizeof(push_addr_frame_t)) typedef struct _detect_addr_frame_t { struct __attribute__((__packed__)) detect_addr_frame_data { unsigned char arg0; // 'd' first detect 'e' echo detect '\0' unsigned char arg1; //保留 unsigned char arg2; //保留 unsigned char arg3; //保留 unsigned char src_key512[64]; //发送节点的key gnb_uuid_t src_uuid64; //发送方的uuid64,可选 gnb_uuid_t dst_uuid64; //目的方的uuid64,可选 uint64_t src_ts_usec; //发送方的时间戳 char text[32]; char attachment[INDEX_ATTACHMENT_SIZE]; }data; unsigned char src_sign[ED25519_SIGN_SIZE]; gnb_uuid_t node_uuid64; }__attribute__ ((__packed__)) detect_addr_frame_t; #pragma pack(pop) #endif opengnb-ver1.6.0.a/src/gnb_index_service_worker.c000077500000000000000000000574541500454252100221230ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 #include #ifdef _WIN32 #define _POSIX #define __USE_MINGW_ALARM #endif #include #include #include #include #include #include #include #include "gnb.h" #include "gnb_node.h" #include "gnb_worker.h" #include "gnb_ring_buffer_fixed.h" #include "gnb_lru32.h" #include "gnb_time.h" #include "gnb_binary.h" #include "gnb_worker_queue_data.h" #include "gnb_index_frame_type.h" typedef struct _index_service_worker_ctx_t { gnb_core_t *gnb_core; //注意,lur 中保存的是数据(gnb_key_address_t)拷贝,不是指针 gnb_lru32_t *lru; gnb_payload16_t *index_frame_payload; uint64_t now_time_sec; uint64_t now_time_usec; pthread_t thread_worker; }index_service_worker_ctx_t; typedef struct _gnb_key_address_t{ gnb_uuid_t uuid64; // key_node 最后发送 post_addr_frame的时间 uint64_t last_post_addr4_sec; uint64_t last_post_addr6_sec; //key_node 最后发送 request_addr_frame 的时间戳 uint64_t last_send_request_addr_usec; //源节点对自身探测的wan地址 uint8_t wan6_addr[16]; uint16_t wan6_port; uint8_t wan4_addr[4]; uint16_t wan4_port; unsigned char node_random_sequence[NODE_RANDOM_SEQUENCE_SIZE]; unsigned char node_random_sequence_sign[ED25519_SIGN_SIZE]; unsigned char address6_list_block[sizeof(gnb_address_list_t) + sizeof(gnb_address_t)*GNB_KEY_ADDRESS_NUM]; unsigned char address4_list_block[sizeof(gnb_address_list_t) + sizeof(gnb_address_t)*GNB_KEY_ADDRESS_NUM]; char attachmenta[INDEX_ATTACHMENT_SIZE]; //保存 PAYLOAD_SUB_TYPE_POST_ADDR 的 attachment char attachmentb[INDEX_ATTACHMENT_SIZE]; //保存 PAYLOAD_SUB_TYPE_POST_ADDR 的 attachment }gnb_key_address_t; static void send_echo_addr_frame(gnb_worker_t *gnb_index_service_worker, unsigned char *key512, gnb_uuid_t uuid64, gnb_address_t *address); static void send_push_addr_frame(gnb_worker_t *gnb_index_service_worker, unsigned char action, unsigned char attachment, unsigned char *src_key, gnb_key_address_t *src_key_address, unsigned char *dst_key, gnb_key_address_t *dst_key_address); static void handle_post_addr_frame(gnb_core_t *gnb_core, gnb_worker_in_data_t *index_service_worker_in_data); static void handle_request_addr_frame(gnb_core_t *gnb_core, gnb_worker_in_data_t *index_service_worker_in_data); static void handle_post_addr_frame(gnb_core_t *gnb_core, gnb_worker_in_data_t *index_service_worker_in_data){ index_service_worker_ctx_t *index_service_worker_ctx = gnb_core->index_service_worker->ctx; gnb_key_address_t *key_address; post_addr_frame_t *post_addr_frame = (post_addr_frame_t *)&index_service_worker_in_data->payload_st.data; gnb_sockaddress_t *sockaddress = &index_service_worker_in_data->node_addr_st; key_address = GNB_LRU32_HASH_GET_VALUE(index_service_worker_ctx->lru, post_addr_frame->data.src_key512, 64); gnb_address_list_t *address6_list; gnb_address_list_t *address4_list; if ( NULL == key_address ) { key_address = (gnb_key_address_t *)alloca( sizeof(gnb_key_address_t) ); memset(key_address,0,sizeof(gnb_key_address_t)); GNB_LRU32_FIXED_STORE(index_service_worker_ctx->lru, post_addr_frame->data.src_key512, 64, key_address); key_address = GNB_LRU32_HASH_GET_VALUE(index_service_worker_ctx->lru, post_addr_frame->data.src_key512, 64); address6_list = (gnb_address_list_t *)key_address->address6_list_block; address6_list->size = GNB_KEY_ADDRESS_NUM; address4_list = (gnb_address_list_t *)key_address->address4_list_block; address4_list->size = GNB_KEY_ADDRESS_NUM; } else { address6_list = (gnb_address_list_t *)key_address->address6_list_block; address4_list = (gnb_address_list_t *)key_address->address4_list_block; } key_address->uuid64 = gnb_ntohll(post_addr_frame->data.src_uuid64); gnb_address_t *address = alloca(sizeof(gnb_address_t)); address->ts_sec = index_service_worker_ctx->now_time_sec; if ( AF_INET6 == sockaddress->addr_type ) { if ( index_service_worker_ctx->now_time_sec - key_address->last_post_addr6_sec < GNB_POST_ADDR_LIMIT_SEC ) { GNB_LOG3(gnb_core->log, GNB_LOG_ID_INDEX_SERVICE_WORKER, "HANDLE POST receive addr=%u now_time_sec=%"PRIu64" last_post_addr6_sec=%"PRIu64" LIMIT\n", key_address->uuid64, index_service_worker_ctx->now_time_sec, key_address->last_post_addr6_sec); key_address->last_post_addr6_sec = index_service_worker_ctx->now_time_sec; return; } key_address->last_post_addr6_sec = index_service_worker_ctx->now_time_sec; gnb_set_address6(address, &sockaddress->addr.in6); gnb_address_list3_fifo(address6_list, address); } if ( AF_INET == sockaddress->addr_type ) { if ( index_service_worker_ctx->now_time_sec - key_address->last_post_addr4_sec < GNB_POST_ADDR_LIMIT_SEC ) { GNB_LOG2(gnb_core->log, GNB_LOG_ID_INDEX_SERVICE_WORKER, "HANDLE POST receive addr=%u now_time_sec=%"PRIu64" last_post_addr4_sec=%"PRIu64" LIMIT\n", key_address->uuid64, index_service_worker_ctx->now_time_sec, key_address->last_post_addr4_sec); key_address->last_post_addr4_sec = index_service_worker_ctx->now_time_sec; return; } key_address->last_post_addr4_sec = index_service_worker_ctx->now_time_sec; gnb_set_address4(address, &sockaddress->addr.in); gnb_address_list3_fifo(address4_list, address); } if ( 0 != post_addr_frame->data.wan6_port ) { memcpy(key_address->wan6_addr,post_addr_frame->data.wan6_addr,16); key_address->wan6_port = post_addr_frame->data.wan6_port; } if ( 'p' == post_addr_frame->data.arg0 ) { if ( 'a' == post_addr_frame->data.arg1 ) { memcpy(key_address->attachmenta, post_addr_frame->data.attachment, INDEX_ATTACHMENT_SIZE); } else if ( 'b' == post_addr_frame->data.arg1 ) { memcpy(key_address->attachmentb, post_addr_frame->data.attachment, INDEX_ATTACHMENT_SIZE); } } send_echo_addr_frame(gnb_core->index_service_worker, post_addr_frame->data.src_key512, key_address->uuid64, address); GNB_LOG3(gnb_core->log, GNB_LOG_ID_INDEX_SERVICE_WORKER, "HANDLE POST addr [%llu][%s]\n", key_address->uuid64, GNB_SOCKETADDRSTR1(sockaddress)); } static void send_echo_addr_frame(gnb_worker_t *gnb_index_service_worker, unsigned char *key512, gnb_uuid_t uuid64, gnb_address_t *address){ index_service_worker_ctx_t *index_service_worker_ctx = gnb_index_service_worker->ctx; gnb_core_t *gnb_core = index_service_worker_ctx->gnb_core; index_service_worker_ctx->index_frame_payload->sub_type = PAYLOAD_SUB_TYPE_ECHO_ADDR; gnb_payload16_set_data_len( index_service_worker_ctx->index_frame_payload, sizeof(echo_addr_frame_t) ); echo_addr_frame_t *echo_addr_frame = (echo_addr_frame_t *)index_service_worker_ctx->index_frame_payload->data; memset(echo_addr_frame, 0, sizeof(echo_addr_frame_t)); memcpy(echo_addr_frame->data.dst_key512, key512, 64); echo_addr_frame->data.dst_uuid64 = gnb_htonll(uuid64); echo_addr_frame->data.src_ts_usec = gnb_htonll(index_service_worker_ctx->now_time_usec); if ( AF_INET6 == address->type ) { echo_addr_frame->data.addr_type = '6'; memcpy(echo_addr_frame->data.addr, address->m_address6, 16); //debug_text snprintf(echo_addr_frame->data.text, 80, "ECHO ADDR [%s:%d][%llu]", GNB_ADDR6STR_PLAINTEXT1(address->m_address6), ntohs(address->port), uuid64); } else if ( AF_INET == address->type ) { echo_addr_frame->data.addr_type = '4'; memcpy(echo_addr_frame->data.addr, address->m_address4, 4); //debug_text snprintf(echo_addr_frame->data.text, 80, "ECHO ADDR [%s:%d][%llu]", GNB_ADDR4STR_PLAINTEXT1(address->m_address4), ntohs(address->port), uuid64 ); } echo_addr_frame->data.port = address->port; gnb_send_to_address(gnb_core, address, index_service_worker_ctx->index_frame_payload); } /* * 把 src_key_address里nodeid及ip地址 发到 dst_key_address 对于的nodeid的节点 */ static void send_push_addr_frame(gnb_worker_t *gnb_index_service_worker, unsigned char action, unsigned char attachment, unsigned char *src_key, gnb_key_address_t *src_key_address, unsigned char *dst_key, gnb_key_address_t *dst_key_address){ index_service_worker_ctx_t *index_service_worker_ctx = gnb_index_service_worker->ctx; gnb_core_t *gnb_core = index_service_worker_ctx->gnb_core; index_service_worker_ctx->index_frame_payload->sub_type = PAYLOAD_SUB_TYPE_PUSH_ADDR; gnb_payload16_set_data_len( index_service_worker_ctx->index_frame_payload, sizeof(push_addr_frame_t) ); push_addr_frame_t *push_addr_frame = (push_addr_frame_t *)index_service_worker_ctx->index_frame_payload->data; memset(push_addr_frame, 0, sizeof(push_addr_frame_t)); memcpy(push_addr_frame->data.node_key, src_key, 64); push_addr_frame->data.node_uuid64 = gnb_htonll(src_key_address->uuid64); gnb_address_list_t *address6_list = (gnb_address_list_t *)src_key_address->address6_list_block; gnb_address_list_t *address4_list = (gnb_address_list_t *)src_key_address->address4_list_block; if ( 0 != address6_list->array[0].port && ( index_service_worker_ctx->now_time_sec - address6_list->array[0].ts_sec < GNB_ADDRESS_LIFE_TIME_TS_SEC) ) { memcpy(&push_addr_frame->data.addr6_a, &address6_list->array[0].address, 16); push_addr_frame->data.port6_a = address6_list->array[0].port; } if ( 0 != address6_list->array[1].port && ( index_service_worker_ctx->now_time_sec - address6_list->array[1].ts_sec < GNB_ADDRESS_LIFE_TIME_TS_SEC) ) { memcpy(&push_addr_frame->data.addr6_b, &address6_list->array[1].address, 16); push_addr_frame->data.port6_b = address6_list->array[1].port; } if ( 0 != address6_list->array[2].port && ( index_service_worker_ctx->now_time_sec - address6_list->array[2].ts_sec < GNB_ADDRESS_LIFE_TIME_TS_SEC) ) { memcpy(&push_addr_frame->data.addr6_c, &address6_list->array[2].address, 16); push_addr_frame->data.port6_c = address6_list->array[2].port; } if ( 0 != address4_list->array[0].port && ( index_service_worker_ctx->now_time_sec - address4_list->array[0].ts_sec < GNB_ADDRESS_LIFE_TIME_TS_SEC) ) { memcpy(&push_addr_frame->data.addr4_a, &address4_list->array[0].address, 4); push_addr_frame->data.port4_a = address4_list->array[0].port; } if ( 0 != address4_list->array[1].port && ( index_service_worker_ctx->now_time_sec - address4_list->array[1].ts_sec < GNB_ADDRESS_LIFE_TIME_TS_SEC) ) { memcpy(&push_addr_frame->data.addr4_b, &address4_list->array[1].address, 4); push_addr_frame->data.port4_b = address4_list->array[1].port; } if ( 0 != address4_list->array[2].port && ( index_service_worker_ctx->now_time_sec - address4_list->array[2].ts_sec < GNB_ADDRESS_LIFE_TIME_TS_SEC) ) { memcpy(&push_addr_frame->data.addr4_c, &address4_list->array[2].address, 4); push_addr_frame->data.port4_c = address4_list->array[2].port; } //找一个空闲的位置,把节点自探测的 wan_addr6 写入 if ( 0 == push_addr_frame->data.port6_a ) { memcpy(&push_addr_frame->data.addr6_a, &src_key_address->wan6_addr, 16); push_addr_frame->data.port6_a = src_key_address->wan6_port; goto finish_fill_address; } if ( 0 == push_addr_frame->data.port6_b ) { memcpy(&push_addr_frame->data.addr6_b, &src_key_address->wan6_addr, 16); push_addr_frame->data.port6_b = src_key_address->wan6_port; goto finish_fill_address; } if ( 0 == push_addr_frame->data.port6_c ) { memcpy(&push_addr_frame->data.addr6_c, &src_key_address->wan6_addr, 16); push_addr_frame->data.port6_c = src_key_address->wan6_port; goto finish_fill_address; } finish_fill_address: push_addr_frame->data.arg0 = action; if ( 'a' == attachment ) { memcpy(push_addr_frame->data.attachment, src_key_address->attachmenta, INDEX_ATTACHMENT_SIZE); } else if ( 'b' == attachment ) { memcpy(push_addr_frame->data.attachment, src_key_address->attachmentb, INDEX_ATTACHMENT_SIZE); } //debug_text snprintf(push_addr_frame->data.text, 32, "INDEX PUSH ADDR[%llu]=>[%llu]", src_key_address->uuid64, dst_key_address->uuid64); gnb_address_list_t *dst_address6_list = (gnb_address_list_t *)dst_key_address->address6_list_block; gnb_address_list_t *dst_address4_list = (gnb_address_list_t *)dst_key_address->address4_list_block; //发给节点所有的活跃地址 gnb_send_available_address_list(gnb_core, dst_address6_list, index_service_worker_ctx->index_frame_payload, index_service_worker_ctx->now_time_sec); gnb_send_available_address_list(gnb_core, dst_address4_list, index_service_worker_ctx->index_frame_payload, index_service_worker_ctx->now_time_sec); GNB_LOG3(gnb_core->log, GNB_LOG_ID_INDEX_SERVICE_WORKER, "SEND PUSH ADDR [%llu]->[%llu]\n", src_key_address->uuid64, dst_key_address->uuid64); } static void handle_request_addr_frame(gnb_core_t *gnb_core, gnb_worker_in_data_t *index_service_worker_in_data){ index_service_worker_ctx_t *index_service_worker_ctx = gnb_core->index_service_worker->ctx; request_addr_frame_t *request_addr_frame = (request_addr_frame_t *)&index_service_worker_in_data->payload_st.data; gnb_sockaddress_t *sockaddress = &index_service_worker_in_data->node_addr_st; gnb_uuid_t src_uuid64 = gnb_ntohll(request_addr_frame->data.src_uuid64); gnb_uuid_t dst_uuid64 = gnb_ntohll(request_addr_frame->data.dst_uuid64); gnb_key_address_t *l_key_address; gnb_key_address_t *r_key_address; l_key_address = GNB_LRU32_HASH_GET_VALUE(index_service_worker_ctx->lru, request_addr_frame->data.src_key512, 64); if ( NULL==l_key_address ) { GNB_LOG3(gnb_core->log, GNB_LOG_ID_INDEX_SERVICE_WORKER, "HANDLE REQUEST src[%llu] => [%llu] l_key_address[%s] is Not Founded\n", src_uuid64, dst_uuid64, GNB_HEX1_BYTE128(request_addr_frame->data.src_key512)); return; } if ( (index_service_worker_ctx->now_time_sec - l_key_address->last_post_addr6_sec) < GNB_POST_ADDR_INTERVAL_TIME_SEC*2 || (index_service_worker_ctx->now_time_sec - l_key_address->last_post_addr4_sec) < GNB_POST_ADDR_INTERVAL_TIME_SEC*2 ) { // l_key_address 里面的地址未超时,将其移到双向链表的首部 GNB_LRU32_MOVETOHEAD(index_service_worker_ctx->lru, request_addr_frame->data.src_key512, 64); } else { GNB_LOG3(gnb_core->log, GNB_LOG_ID_INDEX_SERVICE_WORKER, "HANDLE REQUEST src[%llu] => [%llu] l_key_address[%s] time out now[%"PRIu64"] lastpost6[%"PRIu64"] lastpost4[%"PRIu64"]\n", src_uuid64, dst_uuid64, GNB_HEX1_BYTE128(request_addr_frame->data.src_key512), index_service_worker_ctx->now_time_sec, l_key_address->last_post_addr6_sec, l_key_address->last_post_addr4_sec); return; } //一个节点确实可能需要请求很多节点的信息,没设计好之前暂时不做限制 #if 0 if ( (l_key_address->last_send_request_addr_usec - index_service_worker_ctx->now_time_usec) < GNB_REQUEST_ADDR_LIMIT_USEC ) { return; } #endif l_key_address->last_send_request_addr_usec = index_service_worker_ctx->now_time_usec; r_key_address = GNB_LRU32_HASH_GET_VALUE(index_service_worker_ctx->lru, request_addr_frame->data.dst_key512, 64); if ( NULL==r_key_address ) { GNB_LOG3(gnb_core->log, GNB_LOG_ID_INDEX_SERVICE_WORKER, "HANDLE REQUEST src[%llu] => [%llu] r_key_address[%s] is Not Founded\n", src_uuid64, dst_uuid64, GNB_HEX1_BYTE128(request_addr_frame->data.dst_key512)); return; } if ( (index_service_worker_ctx->now_time_sec - r_key_address->last_post_addr6_sec) < GNB_POST_ADDR_INTERVAL_TIME_SEC*2 || (index_service_worker_ctx->now_time_sec - r_key_address->last_post_addr4_sec) < GNB_POST_ADDR_INTERVAL_TIME_SEC*2 ) { // r_key_address 里面的地址未超时,将其移到双向链表的首部 GNB_LRU32_MOVETOHEAD(index_service_worker_ctx->lru, request_addr_frame->data.dst_key512, 64); } else { GNB_LOG3(gnb_core->log, GNB_LOG_ID_INDEX_SERVICE_WORKER, "HANDLE REQUEST src[%llu] => [%llu] r_key_address[%s] time out now[%"PRIu64"] lastpost6[%"PRIu64"] lastpost4[%"PRIu64"]\n", src_uuid64, dst_uuid64, GNB_HEX1_BYTE128(request_addr_frame->data.dst_key512), index_service_worker_ctx->now_time_sec, r_key_address->last_post_addr6_sec, r_key_address->last_post_addr4_sec); return; } unsigned char attachment = 'a'; if ( 'g' == request_addr_frame->data.arg0 ) { if ( 'a' == request_addr_frame->data.arg1 ) { attachment = 'a'; } else if( 'b' == request_addr_frame->data.arg1 ) { attachment = 'b'; } } //即使节点开启了多个 socket ,index server 只存最近一份地址 gnb_address_list_t *address6_list = (gnb_address_list_t *)l_key_address->address6_list_block; gnb_address_list_t *address4_list = (gnb_address_list_t *)l_key_address->address4_list_block; gnb_address_t *address = alloca(sizeof(gnb_address_t)); address->ts_sec = index_service_worker_ctx->now_time_sec; if ( AF_INET6 == sockaddress->addr_type ) { gnb_set_address6(address, &sockaddress->addr.in6); gnb_address_list3_fifo(address6_list, address); } if ( AF_INET == sockaddress->addr_type ) { gnb_set_address4(address, &sockaddress->addr.in); gnb_address_list3_fifo(address4_list, address); } send_push_addr_frame(gnb_core->index_service_worker, PUSH_ADDR_ACTION_CONNECT, attachment, request_addr_frame->data.src_key512, l_key_address, request_addr_frame->data.dst_key512, r_key_address); send_push_addr_frame(gnb_core->index_service_worker, PUSH_ADDR_ACTION_CONNECT, attachment, request_addr_frame->data.dst_key512, r_key_address, request_addr_frame->data.src_key512, l_key_address); GNB_LOG3(gnb_core->log, GNB_LOG_ID_INDEX_SERVICE_WORKER, "HANDLE REQUEST push addr src[%llu] => [%llu] r_key_address[%s] now[%"PRIu64"] lastpost6[%"PRIu64"] lastpost4[%"PRIu64"]\n", src_uuid64, dst_uuid64, GNB_HEX1_BYTE128(request_addr_frame->data.dst_key512), index_service_worker_ctx->now_time_sec, r_key_address->last_post_addr6_sec, r_key_address->last_post_addr4_sec); } static void handle_index_frame(gnb_core_t *gnb_core, gnb_worker_in_data_t *index_service_worker_in_data){ gnb_payload16_t *payload = &index_service_worker_in_data->payload_st; if ( GNB_PAYLOAD_TYPE_INDEX != payload->type ) { GNB_LOG3(gnb_core->log, GNB_LOG_ID_INDEX_SERVICE_WORKER, "handle_index_frame GNB_PAYLOAD_TYPE_INDEX != payload->type[%x]\n", payload->type); return; } switch( payload->sub_type ) { case PAYLOAD_SUB_TYPE_POST_ADDR: handle_post_addr_frame(gnb_core, index_service_worker_in_data); break; case PAYLOAD_SUB_TYPE_REQUEST_ADDR: handle_request_addr_frame(gnb_core, index_service_worker_in_data); break; default: break; } return; } static void handle_recv_queue(gnb_core_t *gnb_core){ int i; index_service_worker_ctx_t *index_service_worker_ctx = gnb_core->index_service_worker->ctx; gnb_worker_queue_data_t *receive_queue_data; int ret; for ( i=0; i<1024; i++ ) { receive_queue_data = (gnb_worker_queue_data_t *)gnb_ring_buffer_fixed_pop( gnb_core->index_service_worker->ring_buffer_in ); if ( NULL==receive_queue_data ) { break; } handle_index_frame(gnb_core, &receive_queue_data->data.node_in); gnb_ring_buffer_fixed_pop_submit( gnb_core->index_service_worker->ring_buffer_in ); } } static void* thread_worker_func( void *data ) { int ret; gnb_worker_t *gnb_index_service_worker = (gnb_worker_t *)data; index_service_worker_ctx_t *index_service_worker_ctx = gnb_index_service_worker->ctx; gnb_core_t *gnb_core = index_service_worker_ctx->gnb_core; gnb_index_service_worker->thread_worker_flag = 1; gnb_index_service_worker->thread_worker_run_flag = 1; gnb_worker_wait_primary_worker_started(gnb_core); GNB_LOG1(gnb_core->log, GNB_LOG_ID_INDEX_SERVICE_WORKER, "start %s success!\n", gnb_index_service_worker->name); do{ gnb_worker_sync_time(&index_service_worker_ctx->now_time_sec, &index_service_worker_ctx->now_time_usec); handle_recv_queue(gnb_core); GNB_SLEEP_MILLISECOND(150); }while(gnb_index_service_worker->thread_worker_flag); return NULL; } static void init(gnb_worker_t *gnb_worker, void *ctx){ gnb_core_t *gnb_core = (gnb_core_t *)ctx; void *memory; size_t memory_size; index_service_worker_ctx_t *index_service_worker_ctx = (index_service_worker_ctx_t *)gnb_heap_alloc(gnb_core->heap, sizeof(index_service_worker_ctx_t)); memset(index_service_worker_ctx, 0, sizeof(index_service_worker_ctx_t)); index_service_worker_ctx->gnb_core = gnb_core; index_service_worker_ctx->index_frame_payload = (gnb_payload16_t *)gnb_heap_alloc(gnb_core->heap, gnb_core->conf->payload_block_size); index_service_worker_ctx->index_frame_payload->type = GNB_PAYLOAD_TYPE_INDEX; index_service_worker_ctx->lru = gnb_lru32_create(gnb_core->heap, gnb_core->conf->index_service_lru_size, sizeof(gnb_key_address_t)); memory_size = gnb_ring_buffer_fixed_sum_size(GNB_INDEX_SERVICE_WORKER_QUEUE_BLOCK_SIZE, gnb_core->conf->index_service_woker_queue_length); memory = gnb_heap_alloc(gnb_core->heap, memory_size); gnb_worker->ring_buffer_in = gnb_ring_buffer_fixed_init(memory, GNB_INDEX_SERVICE_WORKER_QUEUE_BLOCK_SIZE, gnb_core->conf->index_service_woker_queue_length); gnb_worker->ring_buffer_out = NULL; gnb_worker->ctx = index_service_worker_ctx; GNB_LOG1(gnb_core->log, GNB_LOG_ID_INDEX_SERVICE_WORKER, "%s in ring buffer size = %d\n", gnb_worker->name, gnb_core->conf->index_service_woker_queue_length); GNB_LOG1(gnb_core->log, GNB_LOG_ID_INDEX_SERVICE_WORKER, "%s init finish\n", gnb_worker->name); } static void release(gnb_worker_t *gnb_worker){ index_service_worker_ctx_t *index_service_worker_ctx = (index_service_worker_ctx_t *)gnb_worker->ctx; } static int start(gnb_worker_t *gnb_worker){ index_service_worker_ctx_t *index_service_worker_ctx = gnb_worker->ctx; pthread_create(&index_service_worker_ctx->thread_worker, NULL, thread_worker_func, gnb_worker); pthread_detach(index_service_worker_ctx->thread_worker); return 0; } static int stop(gnb_worker_t *gnb_worker){ index_service_worker_ctx_t *index_service_worker_ctx = gnb_worker->ctx; gnb_core_t *gnb_core = index_service_worker_ctx->gnb_core; gnb_worker_t *index_service_worker = gnb_core->index_service_worker; index_service_worker->thread_worker_flag = 0; return 0; } static int notify(gnb_worker_t *gnb_worker){ int ret; index_service_worker_ctx_t *index_service_worker_ctx = gnb_worker->ctx; ret = pthread_kill(index_service_worker_ctx->thread_worker,SIGALRM); return 0; } gnb_worker_t gnb_index_service_worker_mod = { .name = "gnb_index_service_worker", .init = init, .release = release, .start = start, .stop = stop, .notify = notify, .ctx = NULL }; opengnb-ver1.6.0.a/src/gnb_index_worker.c000077500000000000000000000760061500454252100203750ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 #include #ifdef _WIN32 #define _POSIX #define __USE_MINGW_ALARM #endif #include #include #include #include #include #include #include #include "gnb.h" #include "gnb_node.h" #include "gnb_worker.h" #include "gnb_ring_buffer_fixed.h" #include "gnb_time.h" #include "gnb_binary.h" #include "gnb_worker_queue_data.h" #include "gnb_index_frame_type.h" #include "ed25519/ed25519.h" typedef struct _index_worker_ctx_t { gnb_core_t *gnb_core; gnb_payload16_t *index_frame_payload; struct timeval now_timeval; uint64_t now_time_sec; uint64_t now_time_usec; uint64_t last_post_addr_ts_sec; pthread_t thread_worker; }index_worker_ctx_t; static void send_post_addr_frame(gnb_worker_t *gnb_index_worker){ index_worker_ctx_t *index_worker_ctx = gnb_index_worker->ctx; gnb_core_t *gnb_core = index_worker_ctx->gnb_core; index_worker_ctx->index_frame_payload->sub_type = PAYLOAD_SUB_TYPE_POST_ADDR; gnb_payload16_set_data_len( index_worker_ctx->index_frame_payload, sizeof(post_addr_frame_t) ); post_addr_frame_t *post_addr_frame = (post_addr_frame_t *)index_worker_ctx->index_frame_payload->data; memset(post_addr_frame, 0, sizeof(post_addr_frame_t)); post_addr_frame->data.arg0 = 'p'; post_addr_frame->data.arg1 = 'a'; memcpy(post_addr_frame->data.src_key512, gnb_core->local_node->key512, 64); post_addr_frame->data.src_uuid64 = gnb_htonll(gnb_core->local_node->uuid64); post_addr_frame->data.src_ts_usec = gnb_htonll(index_worker_ctx->now_time_usec); if ( 0 != gnb_core->ctl_block->core_zone->wan6_port ) { memcpy(post_addr_frame->data.wan6_addr, gnb_core->ctl_block->core_zone->wan6_addr, 16); post_addr_frame->data.wan6_port = gnb_core->ctl_block->core_zone->wan6_port; GNB_LOG3(gnb_core->log, GNB_LOG_ID_INDEX_WORKER, "post wan6 address [%s:%d]\n", GNB_ADDR6STR1(post_addr_frame->data.wan6_addr), ntohs(post_addr_frame->data.wan6_port)); } //debug_text snprintf(post_addr_frame->data.text, 32, "[%llu]POST ADDR", gnb_core->local_node->uuid64); //向所有index节点post gnb_send_address_list(gnb_core, gnb_core->index_address_ring.address_list, index_worker_ctx->index_frame_payload); index_worker_ctx->last_post_addr_ts_sec = index_worker_ctx->now_time_sec; int i; for ( i=0; iindex_address_ring.address_list->num; i++ ) { GNB_LOG3(gnb_core->log, GNB_LOG_ID_INDEX_WORKER, "post local address to index %s\n", gnb_get_ip_port_string(&gnb_core->index_address_ring.address_list->array[i], gnb_static_ip_port_string_buffer1, gnb_addr_secure) ); } } static void send_request_addr_frame(gnb_worker_t *gnb_index_worker, gnb_node_t *node){ index_worker_ctx_t *index_worker_ctx = gnb_index_worker->ctx; gnb_core_t *gnb_core = index_worker_ctx->gnb_core; if ( 0 == gnb_core->index_address_ring.address_list->num ) { return; } index_worker_ctx->index_frame_payload->sub_type = PAYLOAD_SUB_TYPE_REQUEST_ADDR; gnb_payload16_set_data_len( index_worker_ctx->index_frame_payload, sizeof(request_addr_frame_t) ); request_addr_frame_t *request_addr_frame = (request_addr_frame_t *)index_worker_ctx->index_frame_payload->data; memset(request_addr_frame, 0, sizeof(request_addr_frame_t)); //请求获取 附件 a request_addr_frame->data.arg0 = 'g'; request_addr_frame->data.arg1 = 'a'; memcpy(request_addr_frame->data.src_key512, gnb_core->local_node->key512, 64); memcpy(request_addr_frame->data.dst_key512, node->key512, 64); request_addr_frame->data.src_uuid64 = gnb_htonll(gnb_core->local_node->uuid64); request_addr_frame->data.dst_uuid64 = gnb_htonll(node->uuid64); request_addr_frame->data.src_ts_usec = gnb_htonll(index_worker_ctx->now_time_usec); //debug_text snprintf(request_addr_frame->data.text,32, "%s %llu==>%llu", "REQUEST_ADDR", gnb_core->local_node->uuid64, node->uuid64); gnb_address_t *address; if ( GNB_MULTI_ADDRESS_TYPE_FULL != gnb_core->conf->multi_index_type ) { address = gnb_select_index_address(gnb_core, index_worker_ctx->now_time_sec); if (NULL!=address) { gnb_send_to_address_through_all_sockets(gnb_core, address, index_worker_ctx->index_frame_payload,1); } } else { //向所有index节点发请求 gnb_send_address_list_through_all_sockets(gnb_core, gnb_core->index_address_ring.address_list, index_worker_ctx->index_frame_payload,1); } node->last_request_addr_sec = index_worker_ctx->now_time_sec; GNB_DEBUG5(gnb_core->log, GNB_LOG_ID_INDEX_WORKER, "SEND REQUEST ADDR %llu ==>%llu lkey[%s] rkey[%s]\n", gnb_core->local_node->uuid64, node->uuid64, GNB_HEX1_BYTE128(gnb_core->local_node->key512), GNB_HEX2_BYTE128(node->key512)); } //地址端口探测 gnb_address_t *address static void send_detect_addr_frame(gnb_worker_t *gnb_index_worker, gnb_address_t *in_address, gnb_uuid_t dst_uuid64){ if ( 0 == in_address->port ) { return; } //因为传入的 in_address 要保留原始的内容在其他地方使用,这里拷贝一份 gnb_address_t address_st; memcpy(&address_st,in_address,sizeof(gnb_address_t)); index_worker_ctx_t *index_worker_ctx = gnb_index_worker->ctx; gnb_core_t *gnb_core = index_worker_ctx->gnb_core; index_worker_ctx->index_frame_payload->sub_type = PAYLOAD_SUB_TYPE_DETECT_ADDR; gnb_payload16_set_data_len( index_worker_ctx->index_frame_payload, sizeof(detect_addr_frame_t) ); detect_addr_frame_t *detect_addr_frame = (detect_addr_frame_t *)index_worker_ctx->index_frame_payload->data; memset(detect_addr_frame, 0, sizeof(detect_addr_frame_t)); detect_addr_frame->data.arg0 = 'd'; memcpy(detect_addr_frame->data.src_key512, gnb_core->local_node->key512, 64); detect_addr_frame->data.src_uuid64 = gnb_htonll(gnb_core->local_node->uuid64); detect_addr_frame->data.dst_uuid64 = gnb_htonll(dst_uuid64); detect_addr_frame->data.src_ts_usec = gnb_htonll(index_worker_ctx->now_time_usec); //debug_text snprintf(detect_addr_frame->data.text,32,"[%llu]DETECT_ADDR[%llu]", gnb_core->local_node->uuid64, dst_uuid64); if ( 0 == gnb_core->conf->lite_mode ) { ed25519_sign(detect_addr_frame->src_sign, (const unsigned char *)&detect_addr_frame->data, sizeof(struct detect_addr_frame_data), gnb_core->ed25519_public_key, gnb_core->ed25519_private_key); } gnb_send_to_address_through_all_sockets(gnb_core, &address_st, index_worker_ctx->index_frame_payload, gnb_core->conf->address_detect_interval_usec); //以下小范围端口探测,只针对ipv4 if ( AF_INET != address_st.type ) { return; } if ( 0==gnb_core->conf->port_detect_range ) { return; } GNB_LOG2(gnb_core->log, GNB_LOG_ID_INDEX_WORKER, "send DETECT %llu ==> %llu address %s port range[%d]\n", gnb_core->local_node->uuid64, dst_uuid64 , GNB_IP_PORT_STR1(&address_st),gnb_core->conf->port_detect_range); uint16_t dst_port = ntohs(address_st.port); int i; for ( i=dst_port-1; i>(dst_port-gnb_core->conf->port_detect_range); i-- ) { if ( i<=1024 ) { break; } address_st.port = htons(i); gnb_send_to_address_through_all_sockets(gnb_core, &address_st, index_worker_ctx->index_frame_payload, 1); } for ( i=dst_port+1; i<(dst_port+gnb_core->conf->port_detect_range); i++ ) { if ( i>65535 ) { break; } address_st.port = htons(i); gnb_send_to_address_through_all_sockets(gnb_core, &address_st, index_worker_ctx->index_frame_payload, 1); } } static void send_detect_addr_frame_arg(gnb_worker_t *gnb_index_worker, gnb_address_t *in_address, gnb_uuid_t dst_uuid64, unsigned char agr0){ if ( 0 == in_address->port ) { return; } //因为传入的 in_address 要保留原始的内容在其他地方使用,这里拷贝一份 gnb_address_t address_st; memcpy(&address_st,in_address,sizeof(gnb_address_t)); index_worker_ctx_t *index_worker_ctx = gnb_index_worker->ctx; gnb_core_t *gnb_core = index_worker_ctx->gnb_core; index_worker_ctx->index_frame_payload->sub_type = PAYLOAD_SUB_TYPE_DETECT_ADDR; gnb_payload16_set_data_len( index_worker_ctx->index_frame_payload, sizeof(detect_addr_frame_t) ); detect_addr_frame_t *detect_addr_frame = (detect_addr_frame_t *)index_worker_ctx->index_frame_payload->data; memset(detect_addr_frame, 0, sizeof(detect_addr_frame_t)); detect_addr_frame->data.arg0 = agr0; memcpy(detect_addr_frame->data.src_key512, gnb_core->local_node->key512, 64); detect_addr_frame->data.src_uuid64 = gnb_htonll(gnb_core->local_node->uuid64); detect_addr_frame->data.dst_uuid64 = gnb_htonll(dst_uuid64); detect_addr_frame->data.src_ts_usec = gnb_htonll(index_worker_ctx->now_time_usec); //debug_text snprintf(detect_addr_frame->data.text,32,"[%llu]DETECT_ADDR[%llu]", gnb_core->local_node->uuid64, dst_uuid64); if ( 0 == gnb_core->conf->lite_mode ) { ed25519_sign(detect_addr_frame->src_sign, (const unsigned char *)&detect_addr_frame->data, sizeof(struct detect_addr_frame_data), gnb_core->ed25519_public_key, gnb_core->ed25519_private_key); } gnb_send_to_address(gnb_core, &address_st, index_worker_ctx->index_frame_payload); } static void detect_node_addr(gnb_worker_t *gnb_index_worker, gnb_node_t *node){ gnb_address_list_t *static_address_list; gnb_address_list_t *dynamic_address_list; gnb_address_list_t *resolv_address_list; gnb_address_list_t *push_address_list; static_address_list = (gnb_address_list_t *)&node->static_address_block; dynamic_address_list = (gnb_address_list_t *)&node->dynamic_address_block; resolv_address_list = (gnb_address_list_t *)&node->resolv_address_block; push_address_list = (gnb_address_list_t *)&node->push_address_block; int i; for ( i=0; inum; i++ ) { send_detect_addr_frame(gnb_index_worker, &static_address_list->array[i],node->uuid64); } for ( i=0; inum; i++ ) { send_detect_addr_frame(gnb_index_worker, &push_address_list->array[i],node->uuid64); } for ( i=0; inum; i++ ) { send_detect_addr_frame(gnb_index_worker, &dynamic_address_list->array[i],node->uuid64); } for ( i=0; inum; i++ ) { send_detect_addr_frame(gnb_index_worker, &resolv_address_list->array[i],node->uuid64); } node->detect_count++; } static void handle_push_addr_frame(gnb_core_t *gnb_core, gnb_worker_in_data_t *index_worker_in_data){ gnb_address_list_t *push_address_list; gnb_address_list_t *detect_address_list; index_worker_ctx_t *index_worker_ctx = gnb_core->index_worker->ctx; push_addr_frame_t *push_addr_frame = (push_addr_frame_t *)&index_worker_in_data->payload_st.data; int i; gnb_uuid_t nodeid = gnb_ntohll(push_addr_frame->data.node_uuid64); gnb_node_t *node; node = GNB_HASH32_UINT64_GET_PTR(gnb_core->uuid_node_map, nodeid); if ( NULL == node ) { return; } if ( node->type & GNB_NODE_TYPE_SLIENCE ) { return; } if ( gnb_core->local_node->uuid64 == node->uuid64 ) { return; } //本地节点如果有 GNB_NODE_TYPE_SLIENCE 属性 将只响应 带有 GNB_NODE_TYPE_FWD 属性的节点 if ( (gnb_core->local_node->type & GNB_NODE_TYPE_SLIENCE) && !(node->type & GNB_NODE_TYPE_FWD) ) { return; } push_address_list = (gnb_address_list_t *)&node->push_address_block; detect_address_list = (gnb_address_list_t *)&node->detect_address4_block; //校验 本地存储的 key512 与 push_addr_frame->data.node_key 是否相同 if ( memcmp(node->key512, push_addr_frame->data.node_key, 64) ) { GNB_LOG2(gnb_core->log,GNB_LOG_ID_INDEX_WORKER, "handle push_addr frame node key not match node[%s] frame[%s]\n", GNB_HEX1_BYTE128(node->key512), GNB_HEX2_BYTE128(push_addr_frame->data.node_key)); return; } gnb_address_list_t *dst_address6_list = alloca( sizeof(gnb_address_list_t) + sizeof(gnb_address_t)*GNB_KEY_ADDRESS_NUM ); memset(dst_address6_list, 0, sizeof(gnb_address_list_t) + sizeof(gnb_address_t)*GNB_KEY_ADDRESS_NUM); dst_address6_list->size = GNB_KEY_ADDRESS_NUM; gnb_address_list_t *dst_address4_list = alloca( sizeof(gnb_address_list_t) + sizeof(gnb_address_t)*GNB_KEY_ADDRESS_NUM ); memset(dst_address4_list, 0, sizeof(gnb_address_list_t) + sizeof(gnb_address_t)*GNB_KEY_ADDRESS_NUM); dst_address4_list->size = GNB_KEY_ADDRESS_NUM; gnb_address_t address_st; memset(&address_st, 0, sizeof(gnb_address_t)); address_st.ts_sec = index_worker_ctx->now_time_sec; address_st.type = AF_INET6; if ( 0 != push_addr_frame->data.port6_a ) { address_st.port = push_addr_frame->data.port6_a; memcpy(&address_st.address.addr6, push_addr_frame->data.addr6_a, 16); gnb_address_list_update(dst_address6_list, &address_st); gnb_address_list_update(push_address_list, &address_st); } if ( 0 != push_addr_frame->data.port6_b ) { address_st.port = push_addr_frame->data.port6_b; memcpy(&address_st.address.addr6, push_addr_frame->data.addr6_b, 16); gnb_address_list_update(dst_address6_list, &address_st); gnb_address_list_update(push_address_list, &address_st); } if ( 0 != push_addr_frame->data.port6_c ) { address_st.port = push_addr_frame->data.port6_c; memcpy(&address_st.address.addr6, push_addr_frame->data.addr6_c, 16); gnb_address_list_update(dst_address6_list, &address_st); gnb_address_list_update(push_address_list, &address_st); } //just for log for ( i=0; inum; i++ ) { GNB_LOG2(gnb_core->log,GNB_LOG_ID_INDEX_WORKER,"RECEIVE_PUSH_ADDR node=%llu %s text='%.*s' action=%c\n", nodeid, GNB_IP_PORT_STR1(&dst_address6_list->array[i]), 32, push_addr_frame->data.text, push_addr_frame->data.arg0); } if ( PUSH_ADDR_ACTION_CONNECT == push_addr_frame->data.arg0 ) { for( i=0; inum; i++ ) { send_detect_addr_frame_arg(gnb_core->index_worker, &dst_address6_list->array[i], nodeid,'d'); } } //下面是处理 ipv4 address_st.type = AF_INET; //由于 detect_address_list 是先进先出,push_addr_frame->data.addr4_a 保存的是最新提交的地址,因此倒序列录入数据,使得最新的地址优先探测 if ( 0 != push_addr_frame->data.port4_c ) { address_st.port = push_addr_frame->data.port4_c; memcpy(&address_st.address.addr4, push_addr_frame->data.addr4_c, 4); gnb_address_list_update(dst_address4_list, &address_st); gnb_address_list_update(push_address_list, &address_st); gnb_address_list3_fifo(detect_address_list, &address_st); } if ( 0 != push_addr_frame->data.port4_b ) { address_st.port = push_addr_frame->data.port4_b; memcpy(&address_st.address.addr4, push_addr_frame->data.addr4_b, 4); gnb_address_list_update(dst_address4_list, &address_st); gnb_address_list_update(push_address_list, &address_st); gnb_address_list3_fifo(detect_address_list, &address_st); } if ( 0 != push_addr_frame->data.port4_a ) { address_st.port = push_addr_frame->data.port4_a; memcpy(&address_st.address.addr4, push_addr_frame->data.addr4_a, 4); gnb_address_list_update(dst_address4_list, &address_st); gnb_address_list_update(push_address_list, &address_st); gnb_address_list3_fifo(detect_address_list, &address_st); } //just for log for ( i=0; inum; i++ ) { GNB_LOG2(gnb_core->log,GNB_LOG_ID_INDEX_WORKER,"RECEIVE_PUSH_ADDR node=%llu %s text='%.*s' action=%c\n", nodeid, GNB_IP_PORT_STR1(&dst_address4_list->array[i]), 32, push_addr_frame->data.text, push_addr_frame->data.arg0); } if ( dst_address6_list->num == 0 && dst_address4_list->num == 0 ) { GNB_LOG2(gnb_core->log,GNB_LOG_ID_INDEX_WORKER,"RECEIVE_PUSH_ADDR ERROR push address incorrect node=%llu text='%.*s' action=%c\n", nodeid, 32, push_addr_frame->data.text, push_addr_frame->data.arg0); return; } node->last_push_addr_sec = index_worker_ctx->now_time_sec; node->detect_count = 0; if ( PUSH_ADDR_ACTION_CONNECT == push_addr_frame->data.arg0 ) { for ( i=0; inum; i++ ) { send_detect_addr_frame(gnb_core->index_worker, &dst_address4_list->array[i], nodeid); } } } static void sync_index_node(gnb_worker_t *gnb_index_worker){ index_worker_ctx_t *index_worker_ctx = gnb_index_worker->ctx; gnb_core_t *gnb_core = index_worker_ctx->gnb_core; gnb_node_t *node; size_t num = gnb_core->ctl_block->node_zone->node_num; if ( 0==num ) { return; } int i; for ( i=0; ictl_block->node_zone->node[i]; if ( gnb_core->local_node->uuid64 == node->uuid64 ) { continue; } if ( node->type & GNB_NODE_TYPE_SLIENCE ) { continue; } //如果本地节点带有 GNB_NODE_TYPE_SLIENCE 属性 将只请求带有 GNB_NODE_TYPE_FWD 属性的节点的地址 if ( (gnb_core->local_node->type & GNB_NODE_TYPE_SLIENCE) && !(node->type & GNB_NODE_TYPE_FWD) ) { continue; } if ( (GNB_NODE_STATUS_IPV6_PONG | GNB_NODE_STATUS_IPV4_PONG) & node->udp_addr_status ) { continue; } //自身的频率限制 if ( (index_worker_ctx->now_time_sec - node->last_request_addr_sec) < GNB_REQUEST_ADDR_INTERVAL_SEC ) { continue; } if ( node->detect_count < GNB_NODE_MAX_DETECT_TIMES ) { detect_node_addr(gnb_index_worker, node); } send_request_addr_frame(gnb_index_worker,node); node->last_request_addr_sec = index_worker_ctx->now_time_sec; } } static void handle_echo_addr_frame(gnb_core_t *gnb_core, gnb_worker_in_data_t *index_worker_in_data){ index_worker_ctx_t *index_worker_ctx = gnb_core->index_worker->ctx; gnb_sockaddress_t *sockaddress = &index_worker_in_data->node_addr_st; echo_addr_frame_t *echo_addr_frame = (echo_addr_frame_t *)&index_worker_in_data->payload_st.data; gnb_uuid_t dst_uuid64 = gnb_ntohll(echo_addr_frame->data.dst_uuid64); if ( dst_uuid64 != gnb_core->local_node->uuid64 ) { return; } gnb_address_t *address = alloca(sizeof(gnb_address_t)); if ( AF_INET6 == sockaddress->addr_type ) { gnb_set_address6(address, &sockaddress->addr.in6); } if ( AF_INET == sockaddress->addr_type ) { gnb_set_address4(address, &sockaddress->addr.in); } /* 如果 index 节点有多个 ipv6 地址,这里得到地址不一定与发送的目的地址相同 */ int idx = gnb_address_list_find(gnb_core->index_address_ring.address_list, address); if ( -1 == idx ) { return; } //更新最后一次在 n 个 index 节点中的其中一个返回echo的时间戳 gnb_core->index_address_ring.address_list->update_sec = index_worker_ctx->now_time_sec; //更新返回 ehco 的index 节点的地址对应的时间戳 gnb_core->index_address_ring.address_list->array[idx].ts_sec = index_worker_ctx->now_time_sec; if ( '6' == echo_addr_frame->data.addr_type ) { memcpy(&gnb_core->local_node->udp_sockaddr6.sin6_addr, &echo_addr_frame->data.addr, 16); gnb_core->local_node->udp_sockaddr6.sin6_port = echo_addr_frame->data.port; GNB_LOG3(gnb_core->log,GNB_LOG_ID_INDEX_WORKER,"get echo address %s:%d from index %s\n", GNB_ADDR6STR1(echo_addr_frame->data.addr), ntohs(echo_addr_frame->data.port), GNB_SOCKETADDRSTR2(sockaddress)); } else if ( '4' == echo_addr_frame->data.addr_type ) { memcpy(&gnb_core->local_node->udp_sockaddr4.sin_addr, &echo_addr_frame->data.addr, 4); gnb_core->local_node->udp_sockaddr4.sin_port = echo_addr_frame->data.port; GNB_LOG3(gnb_core->log,GNB_LOG_ID_INDEX_WORKER,"get echo address %s:%d from index %s\n", GNB_ADDR4STR1(echo_addr_frame->data.addr), ntohs(echo_addr_frame->data.port), GNB_SOCKETADDRSTR2(sockaddress)); } else { GNB_LOG3(gnb_core->log,GNB_LOG_ID_INDEX_WORKER,"handle echo address type error%.*s from %s\n", 80, echo_addr_frame->data.text, GNB_SOCKETADDRSTR2(sockaddress)); return; } } static void handle_detect_addr_frame(gnb_core_t *gnb_core, gnb_worker_in_data_t *index_worker_in_data){ gnb_address_list_t *dynamic_address_list; index_worker_ctx_t *index_worker_ctx = gnb_core->index_worker->ctx; detect_addr_frame_t *detect_addr_frame = (detect_addr_frame_t *)&index_worker_in_data->payload_st.data; gnb_uuid_t src_uuid64 = gnb_ntohll(detect_addr_frame->data.src_uuid64); gnb_uuid_t dst_uuid64 = gnb_ntohll(detect_addr_frame->data.dst_uuid64); gnb_sockaddress_t *sockaddress = &index_worker_in_data->node_addr_st; gnb_node_t *src_node; src_node = GNB_HASH32_UINT64_GET_PTR(gnb_core->uuid_node_map, src_uuid64); if ( NULL==src_node ) { return; } if ( src_node->type & GNB_NODE_TYPE_SLIENCE ) { return; } //本地节点如果有 GNB_NODE_TYPE_SLIENCE 属性 将只响应 带有 GNB_NODE_TYPE_FWD 属性的节点 if ( (gnb_core->local_node->type & GNB_NODE_TYPE_SLIENCE) && !(src_node->type & GNB_NODE_TYPE_FWD) ) { return; } dynamic_address_list = (gnb_address_list_t *)&src_node->dynamic_address_block; if ( 0 != memcmp(src_node->key512, detect_addr_frame->data.src_key512, 64) ) { GNB_LOG2(gnb_core->log,GNB_LOG_ID_INDEX_WORKER,"handle detect addr invalid key512 src=%llu %s !!\n", src_uuid64, GNB_SOCKETADDRSTR1(sockaddress)); return; } if ( 0 == gnb_core->conf->lite_mode && !ed25519_verify(detect_addr_frame->src_sign, (const unsigned char *)&detect_addr_frame->data, sizeof(struct detect_addr_frame_data), src_node->public_key) ) { GNB_LOG2(gnb_core->log,GNB_LOG_ID_INDEX_WORKER,"handle detect addr src=%llu invalid signature %s !!\n", src_uuid64, GNB_SOCKETADDRSTR1(sockaddress)); return; } gnb_address_t *address = alloca(sizeof(gnb_address_t)); memset(address,0,sizeof(gnb_address_t)); address->socket_idx = index_worker_in_data->socket_idx; address->ts_sec = index_worker_ctx->now_time_usec; if ( AF_INET6 == sockaddress->addr_type ) { if ( 0 != gnb_determine_subnet6_prefixlen96(sockaddress->addr.in6.sin6_addr, gnb_core->local_node->tun_ipv6_addr ) ) { GNB_LOG3(gnb_core->log,GNB_LOG_ID_NODE_WORKER, "handle_detect_addr_frame IPV6 Warning src[%u]->dst[%u] idx=%u %s\n", src_node->uuid64, dst_uuid64, index_worker_in_data->socket_idx, GNB_ADDR6STR1(&sockaddress->addr.in6.sin6_addr) ); return; } if ( 'e' == detect_addr_frame->data.arg0 ) { src_node->udp_addr_status |= GNB_NODE_STATUS_IPV6_PONG; src_node->addr6_update_ts_sec = index_worker_ctx->now_time_sec; } else { src_node->udp_addr_status |= GNB_NODE_STATUS_IPV6_PING; } //只有发生改变的时候才更新 if ( 0 != gnb_cmp_sockaddr_in6(&src_node->udp_sockaddr6, &sockaddress->addr.in6) || index_worker_in_data->socket_idx != src_node->socket6_idx ) { src_node->udp_sockaddr6 = sockaddress->addr.in6; src_node->socket6_idx = index_worker_in_data->socket_idx; } gnb_set_address6(address, &sockaddress->addr.in6); GNB_LOG2(gnb_core->log, GNB_LOG_ID_INDEX_WORKER, "==###== RECEIVE_DETECT_ADDR6 node[%llu]->[%llu] idx[%u]%s[%c] ==###==\n", src_uuid64, dst_uuid64, src_node->socket6_idx, GNB_IP_PORT_STR1(address), detect_addr_frame->data.arg0); } if ( AF_INET == sockaddress->addr_type ) { if ( 0 != gnb_determine_subnet4(sockaddress->addr.in.sin_addr, gnb_core->local_node->tun_addr4, gnb_core->local_node->tun_netmask_addr4) ) { GNB_LOG3(gnb_core->log,GNB_LOG_ID_NODE_WORKER, "handle_detect_addr_frame IPV4 Warning src[%llu]->dst[%llu] idx=%u %s\n", src_node->uuid64, dst_uuid64, index_worker_in_data->socket_idx, GNB_ADDR4STR1(&sockaddress->addr.in.sin_addr) ); return; } if ( 'e' == detect_addr_frame->data.arg0 ) { src_node->udp_addr_status |= GNB_NODE_STATUS_IPV4_PONG; src_node->addr4_update_ts_sec = index_worker_ctx->now_time_sec; } else { src_node->udp_addr_status |= GNB_NODE_STATUS_IPV4_PING; } //只有发生改变的时候才更新 if ( 0 != gnb_cmp_sockaddr_in(&src_node->udp_sockaddr4, &sockaddress->addr.in) || index_worker_in_data->socket_idx != src_node->socket4_idx ) { src_node->udp_sockaddr4 = sockaddress->addr.in; src_node->socket4_idx = index_worker_in_data->socket_idx; } gnb_set_address4(address, &sockaddress->addr.in); GNB_LOG2(gnb_core->log, GNB_LOG_ID_INDEX_WORKER, "==###== RECEIVE_DETECT_ADDR4 node[%llu]->[%llu] idx[%u]%s[%c] ==###==\n", src_uuid64, dst_uuid64, src_node->socket4_idx, GNB_IP_PORT_STR1(address), detect_addr_frame->data.arg0); } address->ts_sec = index_worker_ctx->now_time_sec; gnb_address_list_update(dynamic_address_list, address); if ( 'e' != detect_addr_frame->data.arg0 ) { send_detect_addr_frame_arg(gnb_core->index_worker, address, src_uuid64, 'e'); GNB_LOG3(gnb_core->log, GNB_LOG_ID_INDEX_WORKER, "ECHO DETECT -> node[%llu] idx[%u]%s\n", src_uuid64, src_node->socket4_idx, GNB_IP_PORT_STR1(address)); } } static void handle_index_frame(gnb_core_t *gnb_core, gnb_worker_in_data_t *index_worker_in_data){ gnb_payload16_t *payload = &index_worker_in_data->payload_st; if ( GNB_PAYLOAD_TYPE_INDEX != payload->type ) { GNB_LOG2(gnb_core->log, GNB_LOG_ID_INDEX_WORKER, "handle_index_frame GNB_PAYLOAD_TYPE_INDEX != payload->type[%x]\n", payload->type); return; } switch ( payload->sub_type ) { case PAYLOAD_SUB_TYPE_ECHO_ADDR: handle_echo_addr_frame(gnb_core, index_worker_in_data); break; case PAYLOAD_SUB_TYPE_PUSH_ADDR: handle_push_addr_frame(gnb_core, index_worker_in_data); break; case PAYLOAD_SUB_TYPE_DETECT_ADDR: handle_detect_addr_frame(gnb_core, index_worker_in_data); break; default: break; } return; } static void handle_recv_queue(gnb_core_t *gnb_core){ int i; index_worker_ctx_t *index_worker_ctx = gnb_core->index_worker->ctx; gnb_worker_queue_data_t *receive_queue_data; int ret; for ( i=0; i<1024; i++ ) { receive_queue_data = (gnb_worker_queue_data_t *)gnb_ring_buffer_fixed_pop( gnb_core->index_worker->ring_buffer_in ); if ( NULL == receive_queue_data ) { break; } handle_index_frame(gnb_core, &receive_queue_data->data.node_in); gnb_ring_buffer_fixed_pop_submit( gnb_core->index_worker->ring_buffer_in ); } } static void* thread_worker_func( void *data ) { int ret; gnb_worker_t *gnb_index_worker = (gnb_worker_t *)data; index_worker_ctx_t *index_worker_ctx = gnb_index_worker->ctx; gnb_core_t *gnb_core = index_worker_ctx->gnb_core; gnb_index_worker->thread_worker_flag = 1; gnb_index_worker->thread_worker_run_flag = 1; gnb_worker_wait_primary_worker_started(gnb_core); GNB_LOG1(gnb_core->log, GNB_LOG_ID_INDEX_WORKER, "start %s success!\n", gnb_index_worker->name); do{ gnb_worker_sync_time(&index_worker_ctx->now_time_sec, &index_worker_ctx->now_time_usec); handle_recv_queue(gnb_core); if ( 0 == gnb_core->index_address_ring.address_list->num ) { goto next; } if ( (index_worker_ctx->now_time_sec - index_worker_ctx->last_post_addr_ts_sec) > GNB_POST_ADDR_INTERVAL_TIME_SEC ) { send_post_addr_frame(gnb_index_worker); } sync_index_node(gnb_index_worker); next: GNB_SLEEP_MILLISECOND(150); }while(gnb_index_worker->thread_worker_flag); return NULL; } static void init(gnb_worker_t *gnb_worker, void *ctx){ gnb_core_t *gnb_core = (gnb_core_t *)ctx; void *memory; size_t memory_size; index_worker_ctx_t *index_worker_ctx = (index_worker_ctx_t *)gnb_heap_alloc(gnb_core->heap, sizeof(index_worker_ctx_t)); memset(index_worker_ctx, 0, sizeof(index_worker_ctx_t)); index_worker_ctx->index_frame_payload = (gnb_payload16_t *)gnb_heap_alloc(gnb_core->heap, gnb_core->conf->payload_block_size); index_worker_ctx->index_frame_payload->type = GNB_PAYLOAD_TYPE_INDEX; index_worker_ctx->gnb_core = gnb_core; memory_size = gnb_ring_buffer_fixed_sum_size(GNB_INDEX_WORKER_QUEUE_BLOCK_SIZE, gnb_core->conf->index_woker_queue_length); memory = gnb_heap_alloc(gnb_core->heap, memory_size); gnb_worker->ring_buffer_in = gnb_ring_buffer_fixed_init(memory, GNB_INDEX_WORKER_QUEUE_BLOCK_SIZE, gnb_core->conf->index_woker_queue_length); gnb_worker->ring_buffer_out = NULL; gnb_worker->ctx = index_worker_ctx; GNB_LOG1(gnb_core->log, GNB_LOG_ID_INDEX_WORKER, "%s in ring buffer size = %d\n", gnb_worker->name, gnb_core->conf->index_woker_queue_length); GNB_LOG1(gnb_core->log, GNB_LOG_ID_INDEX_WORKER, "%s init finish\n", gnb_worker->name); } static void release(gnb_worker_t *gnb_worker){ index_worker_ctx_t *index_worker_ctx = (index_worker_ctx_t *)gnb_worker->ctx; } static int start(gnb_worker_t *gnb_worker){ index_worker_ctx_t *index_worker_ctx = gnb_worker->ctx; pthread_create(&index_worker_ctx->thread_worker, NULL, thread_worker_func, gnb_worker); pthread_detach(index_worker_ctx->thread_worker); return 0; } static int stop(gnb_worker_t *gnb_worker){ index_worker_ctx_t *index_worker_ctx = gnb_worker->ctx; gnb_core_t *gnb_core = index_worker_ctx->gnb_core; gnb_worker_t *index_worker = gnb_core->index_worker; index_worker->thread_worker_flag = 0; return 0; } static int notify(gnb_worker_t *gnb_worker){ int ret; index_worker_ctx_t *index_worker_ctx = gnb_worker->ctx; ret = pthread_kill(index_worker_ctx->thread_worker,SIGALRM); return 0; } gnb_worker_t gnb_index_worker_mod = { .name = "gnb_index_worker", .init = init, .release = release, .start = start, .stop = stop, .notify = notify, .ctx = NULL }; opengnb-ver1.6.0.a/src/gnb_keys.c000077500000000000000000000152141500454252100166420ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 #include #include #ifdef _WIN32 #include #include #include #define _POSIX_C_SOURCE 1 //使得 localtime_r 等函数有效 #endif #include #include "gnb_binary.h" #include "crypto/random/gnb_random.h" #include "ed25519/ed25519.h" #include "ed25519/sha512.h" #include "gnb_keys.h" /* 固定长度 unsigned char seed[32]; unsigned char signature[64]; unsigned char public_key[32]; unsigned char private_key[64]; unsigned char scalar[32]; unsigned char shared_secret[32]; */ int gnb_load_keypair(gnb_core_t *gnb_core){ int private_file_fd; int public_file_fd; char node_private_file_name[PATH_MAX+NAME_MAX]; char node_public_file_name[PATH_MAX+NAME_MAX]; unsigned char seed[32]; char hex_string[129]; void *p; ssize_t rlen; snprintf(node_private_file_name, PATH_MAX+NAME_MAX, "%s/security/%llu.private", gnb_core->conf->conf_dir, gnb_core->conf->local_uuid); snprintf(node_public_file_name, PATH_MAX+NAME_MAX, "%s/security/%llu.public", gnb_core->conf->conf_dir, gnb_core->conf->local_uuid); private_file_fd = open(node_private_file_name, O_RDONLY); if ( -1 == private_file_fd ) { GNB_ERROR1(gnb_core->log, GNB_LOG_ID_CORE, "load node private file[%s] error\n", node_private_file_name); exit(0); } rlen = read(private_file_fd, hex_string, 128); close(private_file_fd); if ( 128 != rlen ) { GNB_ERROR1(gnb_core->log, GNB_LOG_ID_CORE, "load node private file[%s] key error\n", node_private_file_name); exit(0); } p = gnb_hex2bin(hex_string, gnb_core->ed25519_private_key, 64); if ( NULL==p ) { GNB_ERROR1(gnb_core->log, GNB_LOG_ID_CORE, "setup private key error\n"); exit(0); } public_file_fd = open(node_public_file_name, O_RDONLY); if ( -1 == public_file_fd ) { GNB_ERROR1(gnb_core->log, GNB_LOG_ID_CORE, "load node public file [%s] error\n", node_public_file_name); exit(0); } rlen = read(public_file_fd, hex_string, 64); close(public_file_fd); if ( 64 != rlen ) { GNB_ERROR1(gnb_core->log, GNB_LOG_ID_CORE, "load node public file[%s] key error\n", node_public_file_name); exit(0); } p = gnb_hex2bin(hex_string, gnb_core->ed25519_public_key, 32); if ( NULL==p ) { GNB_ERROR1(gnb_core->log, GNB_LOG_ID_CORE, "setup public key error\n"); exit(0); } return 0; } int gnb_load_public_key(gnb_core_t *gnb_core, gnb_uuid_t uuid64, unsigned char *public_key){ char node_public_file_name[PATH_MAX+NAME_MAX]; int public_file_fd; char hex_string[129]; ssize_t rlen; snprintf(node_public_file_name, PATH_MAX+NAME_MAX, "%s/ed25519/%llu.public", gnb_core->conf->conf_dir, uuid64); public_file_fd = open(node_public_file_name, O_RDONLY); if ( -1 == public_file_fd ) { return -1; } rlen = read(public_file_fd, hex_string, 64); close(public_file_fd); if ( 64 != rlen ) { return -2; } gnb_hex2bin(hex_string, public_key, 32); return 0; } void gnb_build_crypto_key(gnb_core_t *gnb_core, gnb_node_t *node){ //passcode 将在这个函数中发挥比较重要的作用 unsigned char buffer[64+4]; if ( GNB_CRYPTO_KEY_UPDATE_INTERVAL_NONE != gnb_core->conf->crypto_key_update_interval ) { memcpy(buffer,gnb_core->time_seed,32); } else { memcpy(buffer,node->shared_secret,32); } memcpy(buffer+32,node->shared_secret,32); memcpy(buffer+64, gnb_core->conf->crypto_passcode, 4); memcpy(node->pre_crypto_key,node->crypto_key, 64); sha512(buffer, 64+4, node->crypto_key); } /* gnb_update_time_seed gnb_verify_seed_time 用于根据时钟更新加密的密钥 */ void gnb_update_time_seed(gnb_core_t *gnb_core, uint64_t now_sec){ time_t t; struct tm ltm; uint32_t time_seed; t = (time_t)now_sec; gmtime_r(&t, <m); time_seed = ltm.tm_year + ltm.tm_mon + ltm.tm_yday; if ( GNB_CRYPTO_KEY_UPDATE_INTERVAL_HOUR == gnb_core->conf->crypto_key_update_interval ) { time_seed += ltm.tm_hour; } else if ( GNB_CRYPTO_KEY_UPDATE_INTERVAL_MINUTE == gnb_core->conf->crypto_key_update_interval ) { time_seed += ltm.tm_hour; time_seed += ltm.tm_min; } else { time_seed += ltm.tm_hour; } time_seed = htonl(time_seed); sha512((const unsigned char *)(&time_seed), sizeof(uint32_t), gnb_core->time_seed); } int gnb_verify_seed_time(gnb_core_t *gnb_core, uint64_t now_sec){ time_t t; struct tm ltm; int r = 0; t = (time_t)now_sec; gmtime_r(&t, <m); if ( GNB_CRYPTO_KEY_UPDATE_INTERVAL_HOUR == gnb_core->conf->crypto_key_update_interval ) { r = (ltm.tm_hour + 1) - gnb_core->time_seed_update_factor; gnb_core->time_seed_update_factor = ltm.tm_hour+1; } else if ( GNB_CRYPTO_KEY_UPDATE_INTERVAL_MINUTE == gnb_core->conf->crypto_key_update_interval ) { r = (ltm.tm_min+1) - gnb_core->time_seed_update_factor; gnb_core->time_seed_update_factor = (ltm.tm_min+1); } else { r = (ltm.tm_hour+1) - gnb_core->time_seed_update_factor; gnb_core->time_seed_update_factor = ltm.tm_hour+1; } return r; } void gnb_build_passcode(void *passcode_bin, char *string_in) { char passcode_string[9]; size_t passcode_string_len; char *passcode_string_offset; memset(passcode_string, 0, 9); passcode_string_len = strlen(string_in); if ( passcode_string_len>2 && '0' == string_in[0] && 'x' == string_in[1] ) { passcode_string_offset = string_in + 2; passcode_string_len -= 2; } else { passcode_string_offset = string_in; } if ( passcode_string_len > 8 ) { passcode_string_len = 8; } if ( 0 != passcode_string_len ) { memcpy(passcode_string, passcode_string_offset, passcode_string_len); } if ( NULL == gnb_hex2bin(passcode_string, passcode_bin, 4) ) { memcpy(passcode_bin, passcode_string, 4); } } opengnb-ver1.6.0.a/src/gnb_keys.h000077500000000000000000000021701500454252100166440ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 . */ #ifndef GNB_KEYS_H #define GNB_KEYS_H #include "gnb.h" int gnb_load_keypair(gnb_core_t *gnb_core); int gnb_load_public_key(gnb_core_t *gnb_core, gnb_uuid_t uuid64, unsigned char *public_key); void gnb_update_time_seed(gnb_core_t *gnb_core, uint64_t now_sec); int gnb_verify_seed_time(gnb_core_t *gnb_core, uint64_t now_sec); void gnb_build_crypto_key(gnb_core_t *gnb_core, gnb_node_t *node); void gnb_build_passcode(void *passcode_bin, char *string_in); #endif opengnb-ver1.6.0.a/src/gnb_log.c000077500000000000000000000250341500454252100164510ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 #include #include #include #include #include #if defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) || defined(__OpenBSD__) #include #include #include #endif #ifdef _WIN32 #undef _WIN32_WINNT #define _WIN32_WINNT 0x0600 #include #include #endif #include "gnb_log.h" #include "gnb_time.h" #include "gnb_payload16.h" #define GNB_LOG_LINE_MAX 1024*4 static void open_log_file(gnb_log_ctx_t *log){ log->std_fd = open(log->log_file_name_std, O_WRONLY|O_CREAT|O_APPEND, S_IRUSR|S_IWUSR); log->debug_fd = open(log->log_file_name_debug, O_WRONLY|O_CREAT|O_APPEND, S_IRUSR|S_IWUSR); log->error_fd = open(log->log_file_name_error, O_WRONLY|O_CREAT|O_APPEND, S_IRUSR|S_IWUSR); } static void close_log_file_pre_fd(gnb_log_ctx_t *log){ if ( log->pre_std_fd > 0 ) { close(log->pre_std_fd); log->pre_std_fd = -1; } if ( log->pre_debug_fd > 0 ) { close(log->pre_debug_fd); log->pre_debug_fd = -1; } if ( log->pre_error_fd > 0 ) { close(log->pre_error_fd); log->pre_error_fd = -1; } } static void log_file_output(gnb_log_ctx_t *log, uint8_t log_type, char *log_string, int log_string_len){ int ret; switch (log_type) { case GNB_LOG_TYPE_STD: ret = write(log->std_fd, log_string, log_string_len); break; case GNB_LOG_TYPE_DEBUG: ret = write(log->debug_fd, log_string, log_string_len); break; case GNB_LOG_TYPE_ERROR: ret = write(log->error_fd, log_string, log_string_len); break; default: break; } } static void log_console_output(int log_type, char *log_string, int log_string_len){ int rc; switch (log_type) { case GNB_LOG_TYPE_STD: case GNB_LOG_TYPE_DEBUG: rc = write(STDOUT_FILENO, log_string, log_string_len); break; case GNB_LOG_TYPE_ERROR: rc = write(STDERR_FILENO, log_string, log_string_len); break; default: break; } } static void log_udp_output(gnb_log_ctx_t *log, uint8_t log_type, char *log_string, int log_string_len){ struct sockaddr_in6 saddr6; struct sockaddr_in saddr4; if ( log->socket6_fd > 0 ) { memset(&saddr6,0, sizeof(struct sockaddr_in6)); saddr6.sin6_family = AF_INET6; saddr6.sin6_port = log->port6; memcpy(&saddr6.sin6_addr, log->addr6, 16); sendto(log->socket6_fd, log_string, log_string_len, 0, (struct sockaddr *)&saddr6, sizeof(struct sockaddr_in6)); } if ( log->socket4_fd > 0 ) { memset(&saddr4,0, sizeof(struct sockaddr_in)); saddr4.sin_family = AF_INET; saddr4.sin_port = log->port4; memcpy(&saddr4.sin_addr.s_addr, log->addr4, 4); sendto(log->socket4_fd, log_string, log_string_len, 0, (struct sockaddr *)&saddr4, sizeof(struct sockaddr_in)); } } static void log_udp_binary_output(gnb_log_ctx_t *log, uint8_t log_type, uint8_t log_id, char *log_string_buffer, int log_string_len){ struct sockaddr_in6 saddr6; struct sockaddr_in saddr4; uint16_t data_size = (uint16_t)log_string_len; gnb_payload16_t *gnb_payload16 = (gnb_payload16_t *)log_string_buffer; gnb_payload16->type = log->log_payload_type; gnb_payload16->sub_type = log_id; gnb_payload16_set_data_len(gnb_payload16, data_size); if ( log->socket6_fd > 0 ) { memset(&saddr6,0, sizeof(struct sockaddr_in)); saddr6.sin6_family = AF_INET6; saddr6.sin6_port = log->port6; memcpy(&saddr6.sin6_addr, log->addr6, 16); sendto(log->socket6_fd, (void *)gnb_payload16, data_size+4, 0, (struct sockaddr *)&saddr6, sizeof(struct sockaddr_in6)); } if ( log->socket4_fd > 0 ) { memset(&saddr4,0, sizeof(struct sockaddr_in)); saddr4.sin_family = AF_INET; saddr4.sin_port = log->port4; memcpy(&saddr4.sin_addr.s_addr, log->addr4, 4); sendto(log->socket4_fd, (void *)gnb_payload16, data_size+4, 0, (struct sockaddr *)&saddr4, sizeof(struct sockaddr_in)); } } void gnb_logf(gnb_log_ctx_t *log, uint8_t log_type, uint8_t log_id, uint8_t level, const char *format, ...){ char now_time_string[GNB_TIME_STRING_MAX]; char log_string_buffer[GNB_LOG_LINE_MAX+4]; char *log_string; int log_string_len; int len; char *p; //加上 一个 offset 4 用于后面的 udp binary output 可以加上一个4字节的 gnb_payload 首部 log_string = log_string_buffer+4; p = log_string; gnb_now_timef("%y-%m-%d %H:%M:%S", now_time_string, GNB_TIME_STRING_MAX); len = snprintf(p, GNB_LOG_LINE_MAX, "%s %s ", now_time_string, log->config_table[log_id].log_name); log_string_len = len; if ( log_string_len > GNB_LOG_LINE_MAX ) { return; } p += log_string_len; va_list ap; va_start(ap, format); len = vsnprintf(p, GNB_LOG_LINE_MAX-log_string_len, format, ap); va_end(ap); log_string_len += len; if ( log_string_len > GNB_LOG_LINE_MAX ) { return; } if ( log->output_type & GNB_LOG_OUTPUT_STDOUT ) { log_console_output(log_type, log_string, log_string_len); } if ( log->output_type & GNB_LOG_OUTPUT_FILE ) { log_file_output(log, log_type, log_string, log_string_len); } if ( log->output_type & GNB_LOG_OUTPUT_UDP ) { if ( GNB_LOG_UDP_TYPE_BINARY == log->log_udp_type ) { log_udp_binary_output(log, log_type, log_id, log_string_buffer, log_string_len); } else { log_udp_output(log, log_type, log_string, log_string_len); } } } int gnb_log_udp_open(gnb_log_ctx_t *log){ struct sockaddr_in6 svr_addr6; struct sockaddr_in svr_addr; int on; int ret; log->socket6_fd = socket(AF_INET6, SOCK_DGRAM, 0); on = 1; setsockopt(log->socket6_fd, SOL_SOCKET, SO_REUSEADDR,(char *)&on, sizeof(on)); on = 1; setsockopt(log->socket6_fd, IPPROTO_IPV6, IPV6_V6ONLY,(char *)&on, sizeof(on)); memset(&svr_addr6,0, sizeof(struct sockaddr_in6)); svr_addr6.sin6_family = AF_INET6; svr_addr6.sin6_port = 0; svr_addr6.sin6_addr = in6addr_any; ret = bind(log->socket6_fd, (struct sockaddr *)&svr_addr6, sizeof(struct sockaddr_in6)); log->socket4_fd = socket(AF_INET, SOCK_DGRAM, 0); on = 1; setsockopt(log->socket4_fd, SOL_SOCKET, SO_REUSEADDR,(char *)&on, sizeof(on) ); memset(&svr_addr,0, sizeof(struct sockaddr_in)); svr_addr.sin_family = AF_INET; svr_addr.sin_port = 0; svr_addr.sin_addr.s_addr = htonl(INADDR_ANY); ret = bind(log->socket4_fd, (struct sockaddr *)&svr_addr, sizeof(struct sockaddr_in)); memcpy(log->addr6, &in6addr_loopback, 16); log->port6 = htons(9000); *((uint32_t *)log->addr4) = htonl(INADDR_LOOPBACK); log->port4 = htons(9000); return 0; } int gnb_log_udp_set_addr4(gnb_log_ctx_t *log, char *ip, uint16_t port4){ inet_pton(AF_INET, ip, (struct in_addr *)log->addr4); log->port4 = htons(port4); return 0; } int gnb_log_udp_set_addr6(gnb_log_ctx_t *log, char *ip, uint16_t port6){ inet_pton(AF_INET6, ip, (struct in6_addr *)log->addr6); log->port6 = htons(port6); return 0; } int gnb_log_udp_set_addr4_string(gnb_log_ctx_t *log, char *sockaddress4_string){ unsigned long int ul; #define MAX_SOCKADDRESS_STRING ( 16 + 1 + sizeof("65535") ) char sockaddress4_string_copy[MAX_SOCKADDRESS_STRING+1]; int sockaddress4_string_len = strlen(sockaddress4_string); if ( sockaddress4_string_len > MAX_SOCKADDRESS_STRING ) { return -1; } strncpy(sockaddress4_string_copy, sockaddress4_string, MAX_SOCKADDRESS_STRING); int i; char *p = sockaddress4_string_copy; for ( i=0; iport4 = htons(port); inet_pton(AF_INET, sockaddress4_string_copy, (struct in_addr *)log->addr4); return 0; } gnb_log_ctx_t* gnb_log_ctx_create(){ gnb_log_ctx_t *log = (gnb_log_ctx_t *)malloc(sizeof(gnb_log_ctx_t)); memset(log, 0, sizeof(gnb_log_ctx_t)); log->std_fd = -1; log->debug_fd = -1; log->error_fd = -1; log->pre_std_fd = -1; log->pre_debug_fd = -1; log->pre_error_fd = -1; log->socket6_fd = -1; log->socket4_fd = -1; return log; } int gnb_log_file_rotate(gnb_log_ctx_t *log){ char now_time_string[GNB_TIME_STRING_MAX]; char archive_name[PATH_MAX+NAME_MAX]; int mday = gnb_now_mday(); if (mday == log->pre_mday) { close_log_file_pre_fd(log); return 0; } if ( !(log->output_type & GNB_LOG_OUTPUT_FILE) ) { return 1; } log->pre_mday = mday; gnb_now_timef("%Y_%m_%d",now_time_string,GNB_TIME_STRING_MAX); snprintf(archive_name, PATH_MAX+NAME_MAX, "%s/std_%s.log.arc", log->log_file_path, now_time_string); rename( (const char *)log->log_file_name_std, (const char *)archive_name ); log->pre_std_fd = log->std_fd; log->pre_debug_fd = log->debug_fd; snprintf(archive_name, PATH_MAX+NAME_MAX, "%s/debug_%s.log.arc", log->log_file_path, now_time_string); rename( (const char *)log->log_file_name_debug, (const char *)archive_name ); log->pre_error_fd = log->error_fd; snprintf(archive_name, PATH_MAX+NAME_MAX, "%s/error_%s.log.arc", log->log_file_path, now_time_string); rename( (const char *)log->log_file_name_error, (const char *)archive_name ); open_log_file(log); return 0; } opengnb-ver1.6.0.a/src/gnb_log.h000077500000000000000000000347301500454252100164610ustar00rootroot00000000000000/* Copyright (C) 2019 gnbdev 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 . */ #ifndef GNB_LOG_H #define GNB_LOG_H #include #include "gnb_log_type.h" gnb_log_ctx_t* gnb_log_ctx_create(); #define GNB_LOG_TYPE_STD 0 #define GNB_LOG_TYPE_DEBUG 1 #define GNB_LOG_TYPE_ERROR 2 //log level越大,日志信息越详细,0不输出日志 #define GNB_LOG_LEVEL_UNSET 0xFF #define GNB_LOG_LEVEL0 0 #define GNB_LOG_LEVEL1 1 #define GNB_LOG_LEVEL2 2 #define GNB_LOG_LEVEL3 3 #define GNB_LOG_LEVEL4 4 #define GNB_LOG_LEVEL5 5 /* level 控制 console file udp 的输出 STD DEBUG ERROR 只是作为一种日志的内置标签,不通过 level 细分控制 要控制 debug 输出,可以让STD 使用小的level,DEBUG用高的level */ void gnb_logf(gnb_log_ctx_t *log, uint8_t log_type, uint8_t log_id, uint8_t level, const char *format, ...); int gnb_log_udp_open(gnb_log_ctx_t *log); int gnb_log_file_rotate(gnb_log_ctx_t *log); int gnb_log_udp_set_addr4(gnb_log_ctx_t *log, char *ip, uint16_t port4); int gnb_log_udp_set_addr6(gnb_log_ctx_t *log, char *ip, uint16_t port6); int gnb_log_udp_set_addr4_string(gnb_log_ctx_t *log, char *sockaddress4_string); #define GNB_LOG1(log,log_id,format,...) \ do{ \ if ( NULL != log && GNB_LOG_OUTPUT_NONE != log->output_type && \ (log->config_table[log_id].console_level >= GNB_LOG_LEVEL1 || \ log->config_table[log_id].file_level >= GNB_LOG_LEVEL1 || \ log->config_table[log_id].udp_level >= GNB_LOG_LEVEL1) \ ){ \ gnb_logf(log,GNB_LOG_TYPE_STD, log_id, GNB_LOG_LEVEL1, format, ##__VA_ARGS__); \ } \ }while(0); #define GNB_LOG2(log,log_id,format,...) \ do{ \ if ( NULL != log && GNB_LOG_OUTPUT_NONE != log->output_type && \ (log->config_table[log_id].console_level >= GNB_LOG_LEVEL2 || \ log->config_table[log_id].file_level >= GNB_LOG_LEVEL2 || \ log->config_table[log_id].udp_level >= GNB_LOG_LEVEL2) \ ){ \ gnb_logf(log,GNB_LOG_TYPE_STD, log_id, GNB_LOG_LEVEL2, format, ##__VA_ARGS__); \ } \ }while(0); #define GNB_LOG3(log,log_id,format,...) \ do{ \ if ( NULL != log && GNB_LOG_OUTPUT_NONE != log->output_type && \ (log->config_table[log_id].console_level >= GNB_LOG_LEVEL3 || \ log->config_table[log_id].file_level >= GNB_LOG_LEVEL3 || \ log->config_table[log_id].udp_level >= GNB_LOG_LEVEL3) \ ){ \ gnb_logf(log,GNB_LOG_TYPE_STD, log_id, GNB_LOG_LEVEL3, format, ##__VA_ARGS__); \ } \ }while(0); #define GNB_LOG4(log,log_id,format,...) \ do{ \ if ( NULL != log && GNB_LOG_OUTPUT_NONE != log->output_type && \ (log->config_table[log_id].console_level >= GNB_LOG_LEVEL4 || \ log->config_table[log_id].file_level >= GNB_LOG_LEVEL4 || \ log->config_table[log_id].udp_level >= GNB_LOG_LEVEL4) \ ){ \ gnb_logf(log, GNB_LOG_TYPE_STD, log_id, GNB_LOG_LEVEL4, format, ##__VA_ARGS__); \ } \ }while(0); #define GNB_LOG5(log,log_id,format,...) \ do{ \ if ( NULL != log && GNB_LOG_OUTPUT_NONE != log->output_type && \ (log->config_table[log_id].console_level >= GNB_LOG_LEVEL5 || \ log->config_table[log_id].file_level >= GNB_LOG_LEVEL5 || \ log->config_table[log_id].udp_level >= GNB_LOG_LEVEL5) \ ){ \ gnb_logf(log, GNB_LOG_TYPE_STD, log_id, GNB_LOG_LEVEL5, format, ##__VA_ARGS__); \ } \ }while(0); #define GNB_DEBUG1(log,log_id,format,...) \ do{ \ if ( NULL != log && GNB_LOG_OUTPUT_NONE != log->output_type && \ (log->config_table[log_id].console_level >= GNB_LOG_LEVEL1 || \ log->config_table[log_id].file_level >= GNB_LOG_LEVEL1 || \ log->config_table[log_id].udp_level >= GNB_LOG_LEVEL1) \ ){ \ gnb_logf(log, GNB_LOG_TYPE_DEBUG, log_id, GNB_LOG_LEVEL1, format, ##__VA_ARGS__); \ } \ }while(0); #define GNB_DEBUG2(log,log_id,format,...) \ do{ \ if ( NULL != log && GNB_LOG_OUTPUT_NONE != log->output_type && \ (log->config_table[log_id].console_level >= GNB_LOG_LEVEL2 || \ log->config_table[log_id].file_level >= GNB_LOG_LEVEL2 || \ log->config_table[log_id].udp_level >= GNB_LOG_LEVEL2) \ ){ \ gnb_logf(log, GNB_LOG_TYPE_DEBUG, log_id, GNB_LOG_LEVEL2, format, ##__VA_ARGS__); \ } \ }while(0); #define GNB_DEBUG3(log,log_id,format,...) \ do{ \ if ( NULL != log && GNB_LOG_OUTPUT_NONE != log->output_type && \ (log->config_table[log_id].console_level >= GNB_LOG_LEVEL3 || \ log->config_table[log_id].file_level >= GNB_LOG_LEVEL3 || \ log->config_table[log_id].udp_level >= GNB_LOG_LEVEL3) \ ){ \ gnb_logf(log, GNB_LOG_TYPE_DEBUG, log_id, GNB_LOG_LEVEL3, format, ##__VA_ARGS__); \ } \ }while(0); #define GNB_DEBUG4(log,log_id,format,...) \ do{ \ if ( NULL != log && GNB_LOG_OUTPUT_NONE != log->output_type && \ (log->config_table[log_id].console_level >= GNB_LOG_LEVEL4 || \ log->config_table[log_id].file_level >= GNB_LOG_LEVEL4 || \ log->config_table[log_id].udp_level >= GNB_LOG_LEVEL4) \ ){ \ gnb_logf(log, GNB_LOG_TYPE_DEBUG, log_id, GNB_LOG_LEVEL4, format, ##__VA_ARGS__); \ } \ }while(0); #define GNB_DEBUG5(log,log_id,format,...) \ do{ \ if ( NULL != log && GNB_LOG_OUTPUT_NONE != log->output_type && \ (log->config_table[log_id].console_level >= GNB_LOG_LEVEL5 || \ log->config_table[log_id].file_level >= GNB_LOG_LEVEL5 || \ log->config_table[log_id].udp_level >= GNB_LOG_LEVEL5) \ ){ \ gnb_logf(log, GNB_LOG_TYPE_DEBUG, log_id, GNB_LOG_LEVEL5, format, ##__VA_ARGS__); \ } \ }while(0); #define GNB_ERROR1(log,log_id,format,...) \ do{ \ if ( NULL != log && GNB_LOG_OUTPUT_NONE != log->output_type && \ (log->config_table[log_id].console_level >= GNB_LOG_LEVEL1 || \ log->config_table[log_id].file_level >= GNB_LOG_LEVEL1 || \ log->config_table[log_id].udp_level >= GNB_LOG_LEVEL1) \ ){ \ gnb_logf(log, GNB_LOG_TYPE_ERROR, log_id, GNB_LOG_LEVEL1, format, ##__VA_ARGS__); \ } \ }while(0); #define GNB_ERROR2(log,log_id,format,...) \ do{ \ if ( NULL != log && GNB_LOG_OUTPUT_NONE != log->output_type && \ (log->config_table[log_id].console_level >= GNB_LOG_LEVEL2 || \ log->config_table[log_id].file_level >= GNB_LOG_LEVEL2 || \ log->config_table[log_id].udp_level >= GNB_LOG_LEVEL2) \ ){ \ gnb_logf(log, GNB_LOG_TYPE_ERROR, log_id, GNB_LOG_LEVEL2, format, ##__VA_ARGS__); \ } \ }while(0); #define GNB_ERROR3(log,log_id,format,...) \ do{ \ if ( NULL != log && GNB_LOG_OUTPUT_NONE != log->output_type && \ (log->config_table[log_id].console_level >= GNB_LOG_LEVEL3 || \ log->config_table[log_id].file_level >= GNB_LOG_LEVEL3 || \ log->config_table[log_id].udp_level >= GNB_LOG_LEVEL3) \ ){ \ gnb_logf(log, GNB_LOG_TYPE_ERROR, log_id, GNB_LOG_LEVEL3, format, ##__VA_ARGS__); \ } \ }while(0); #define GNB_ERROR4(log,log_id,format,...) \ do{ \ if ( NULL != log && GNB_LOG_OUTPUT_NONE != log->output_type && \ (log->config_table[log_id].console_level >= GNB_LOG_LEVEL4 || \ log->config_table[log_id].file_level >= GNB_LOG_LEVEL4 || \ log->config_table[log_id].udp_level >= GNB_LOG_LEVEL4) \ ){ \ gnb_logf(log, GNB_LOG_TYPE_ERROR, log_id, GNB_LOG_LEVEL4, format, ##__VA_ARGS__); \ } \ }while(0); #define GNB_ERROR5(log,log_id,format,...) \ do{ \ if ( NULL != log && GNB_LOG_OUTPUT_NONE != log->output_type && \ (log->config_table[log_id].console_level >= GNB_LOG_LEVEL5 || \ log->config_table[log_id].file_level >= GNB_LOG_LEVEL5 || \ log->config_table[log_id].udp_level >= GNB_LOG_LEVEL5) \ ){ \ gnb_logf(log, GNB_LOG_TYPE_ERROR, log_id, GNB_LOG_LEVEL5, format, ##__VA_ARGS__); \ } \ }while(0); #endif opengnb-ver1.6.0.a/src/gnb_log_type.h000077500000000000000000000037041500454252100175170ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 . */ #ifndef GNB_LOG_TYPE_H #define GNB_LOG_TYPE_H #include #include #include #ifdef _WIN32 #ifndef NAME_MAX #define NAME_MAX 255 #endif #endif typedef struct _gnb_log_config_t { char log_name[20]; uint8_t console_level; uint8_t file_level; uint8_t udp_level; }gnb_log_config_t; #define GNB_MAX_LOG_ID 128 typedef struct _gnb_log_ctx_t { #define GNB_LOG_OUTPUT_NONE (0x0) #define GNB_LOG_OUTPUT_STDOUT (0x1) #define GNB_LOG_OUTPUT_FILE (0x1 << 1) #define GNB_LOG_OUTPUT_UDP (0x1 << 2) unsigned char output_type; char log_file_path[PATH_MAX]; //char log_file_prefix[32]; char log_file_name_std[PATH_MAX+NAME_MAX]; char log_file_name_debug[PATH_MAX+NAME_MAX]; char log_file_name_error[PATH_MAX+NAME_MAX]; int std_fd; int debug_fd; int error_fd; int pre_std_fd; int pre_debug_fd; int pre_error_fd; int pre_mday; uint8_t addr4[4]; uint16_t port4; uint8_t addr6[16]; uint16_t port6; int socket6_fd; int socket4_fd; #define GNB_LOG_UDP_TYPE_TEXT 0 #define GNB_LOG_UDP_TYPE_BINARY 1 uint8_t log_udp_type; //如果 log_udp_type 为 GNB_LOG_UDP_TYPE_BINARY,就需要提供gnb_payload的类型 char log_payload_type; gnb_log_config_t config_table[GNB_MAX_LOG_ID]; }gnb_log_ctx_t; #endif opengnb-ver1.6.0.a/src/gnb_lru32.c000077500000000000000000000242311500454252100166350ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 #include #include "gnb_lru32.h" #include "gnb_doubly_linked_list.h" static gnb_lru32_node_t *gnb_lru32_node_fixed_pool_pop(gnb_lru32_t *lru){ gnb_lru32_node_t *lru_node = NULL; lru_node = gnb_fixed_pool_pop(lru->lru_node_fixed_pool); lru_node->dl_node = gnb_fixed_pool_pop(lru->dl_node_fixed_pool); if (0 != lru->block_size) { lru_node->udata = gnb_fixed_pool_pop(lru->udata_fixed_pool); } return lru_node; } static void gnb_lru32_node_fixed_pool_push(gnb_lru32_t *lru, gnb_lru32_node_t *lru_node){ gnb_fixed_pool_push(lru->dl_node_fixed_pool,lru_node->dl_node); if (0 != lru->block_size) { gnb_fixed_pool_push(lru->udata_fixed_pool,lru_node->udata); } gnb_fixed_pool_push(lru->lru_node_fixed_pool,lru_node); } gnb_lru32_t *gnb_lru32_create(gnb_heap_t *heap, uint32_t max_size,uint32_t block_size){ gnb_lru32_t *lru = (gnb_lru32_t *)gnb_heap_alloc(heap,sizeof(gnb_lru32_t)); lru->heap = heap; lru->max_size = max_size; lru->size = 0; lru->block_size = block_size; lru->lru_node_map = gnb_hash32_create(heap,max_size,max_size); if (NULL==lru->lru_node_map) { gnb_heap_free(heap,lru); return NULL; } lru->doubly_linked_list = gnb_doubly_linked_list_create(lru->heap); if ( 0 != lru->block_size ) { lru->udata_fixed_pool = gnb_fixed_pool_create(heap,max_size, lru->block_size); } lru->dl_node_fixed_pool = gnb_fixed_pool_create(heap,max_size, sizeof(gnb_doubly_linked_list_node_t)); lru->lru_node_fixed_pool = gnb_fixed_pool_create(heap,max_size, sizeof(gnb_lru32_node_t)); return lru; } void gnb_lru32_release(gnb_lru32_t *lru){ if ( 0 != lru->block_size ) { gnb_fixed_pool_release(lru->heap,lru->udata_fixed_pool); } gnb_fixed_pool_release(lru->heap,lru->dl_node_fixed_pool); gnb_fixed_pool_release(lru->heap,lru->lru_node_fixed_pool); gnb_hash32_release(lru->lru_node_map); gnb_doubly_linked_list_release(lru->doubly_linked_list); gnb_heap_free(lru->heap,lru); } void* gnb_lru32_put(gnb_lru32_t *lru, unsigned char *key, uint32_t key_len, void *data){ gnb_lru32_node_t *lru_node; lru_node = gnb_lru32_get(lru, key, key_len); if ( NULL != lru_node ) { if (data==lru_node->udata) { return NULL; } lru_node->udata = data; return NULL; } void *pop_udata = NULL; if ( lru->size >= lru->max_size ) { pop_udata = gnb_lru32_pop_tail(lru); } lru_node = gnb_lru32_node_fixed_pool_pop(lru); if (NULL==lru_node) { //如果链表满了无法set进去,就把传入的指针返回,让调用者处理 return data; } lru_node->udata = data; gnb_doubly_linked_list_add(lru->doubly_linked_list, lru_node->dl_node); gnb_hash32_set(lru->lru_node_map, key, (uint32_t)key_len, lru_node, 0); lru_node->kv = gnb_hash32_get(lru->lru_node_map, key, (uint32_t)key_len); gnb_doubly_linked_list_node_set(lru_node->dl_node,lru_node); lru->size++; return pop_udata; } void gnb_lru32_store(gnb_lru32_t *lru, unsigned char *key, uint32_t key_len, void *data, uint32_t size){ gnb_lru32_node_t *lru_node; lru_node = gnb_lru32_get(lru, key, key_len); if ( NULL != lru_node ) { if (NULL!=lru_node->udata) { gnb_heap_free(lru->heap,lru_node->udata); } lru_node->udata = gnb_heap_alloc(lru->heap,size); memcpy(lru_node->udata,data,size); return; } void *pop_udata = NULL; if ( lru->size >= lru->max_size ) { pop_udata = gnb_lru32_pop_tail(lru); if (NULL!=pop_udata) { gnb_heap_free(lru->heap,pop_udata); } } lru_node = gnb_lru32_node_fixed_pool_pop(lru); if (NULL==lru_node) { return; } lru_node->udata = gnb_heap_alloc(lru->heap,size); memcpy(lru_node->udata,data,size); gnb_doubly_linked_list_add(lru->doubly_linked_list, lru_node->dl_node); gnb_hash32_set(lru->lru_node_map, key, (uint32_t)key_len, lru_node, 0); lru_node->kv = gnb_hash32_get(lru->lru_node_map, key, (uint32_t)key_len); gnb_doubly_linked_list_node_set(lru_node->dl_node,lru_node); lru->size++; return; } void gnb_lru32_fixed_store(gnb_lru32_t *lru, unsigned char *key, uint32_t key_len, void *data){ gnb_lru32_node_t *lru_node; if ( 0 == lru->block_size ) { return; } lru_node = gnb_lru32_get(lru, key, key_len); if ( NULL != lru_node ) { memcpy(lru_node->udata,data,lru->block_size); return; } void *pop_udata = NULL; if ( lru->size >= lru->max_size ) { pop_udata = gnb_lru32_pop_tail(lru); } lru_node = gnb_lru32_node_fixed_pool_pop(lru); if ( NULL == lru_node ) { return; } memcpy(lru_node->udata,data,lru->block_size); gnb_doubly_linked_list_add(lru->doubly_linked_list, lru_node->dl_node); gnb_hash32_set(lru->lru_node_map, key, (uint32_t)key_len, lru_node, 0); lru_node->kv = gnb_hash32_get(lru->lru_node_map, key, (uint32_t)key_len); gnb_doubly_linked_list_node_set(lru_node->dl_node,lru_node); lru->size++; return; } gnb_lru32_node_t* gnb_lru32_hash_get(gnb_lru32_t *lru, unsigned char *key, uint32_t key_len){ gnb_kv32_t *kv32 = gnb_hash32_get(lru->lru_node_map, key, (uint32_t)key_len); if (NULL==kv32) { return NULL; } gnb_lru32_node_t *lru_node = GNB_HASH32_VALUE_PTR(kv32); return lru_node; } gnb_lru32_node_t* gnb_lru32_get(gnb_lru32_t *lru, unsigned char *key, uint32_t key_len){ gnb_kv32_t *kv32 = gnb_hash32_get(lru->lru_node_map, key, (uint32_t)key_len); if (NULL==kv32) { return NULL; } gnb_lru32_node_t *lru_node = GNB_HASH32_VALUE_PTR(kv32); if ( NULL != lru_node ) { gnb_doubly_linked_list_move_head(lru->doubly_linked_list, lru_node->dl_node); } return lru_node; } void gnb_lru32_movetohead(gnb_lru32_t *lru, unsigned char *key, uint32_t key_len){ gnb_kv32_t *kv32 = gnb_hash32_get(lru->lru_node_map, key, (uint32_t)key_len); if (NULL==kv32) { return; } gnb_lru32_node_t *lru_node = GNB_HASH32_VALUE_PTR(kv32); if ( NULL != lru_node ) { gnb_doubly_linked_list_move_head(lru->doubly_linked_list, lru_node->dl_node); } } void* gnb_lru32_pop_by_key(gnb_lru32_t *lru, unsigned char *key, uint32_t key_len){ gnb_lru32_node_t *pop_lru_node; gnb_doubly_linked_list_node_t *dl_node; void *pop_udata; pop_lru_node = gnb_lru32_get(lru, key, key_len); if ( NULL == pop_lru_node ) { return NULL; } dl_node = pop_lru_node->dl_node; gnb_doubly_linked_list_pop(lru->doubly_linked_list, dl_node); pop_udata = pop_lru_node->udata; gnb_kv32_t *kv32 = gnb_hash32_del(lru->lru_node_map, pop_lru_node->kv->key->data, pop_lru_node->kv->key->size); if (NULL!=kv32) { gnb_kv32_release(lru->lru_node_map,kv32); } gnb_lru32_node_fixed_pool_push(lru, pop_lru_node); lru->size--; return pop_udata; } void* gnb_lru32_pop_head(gnb_lru32_t *lru){ void *pop_udata = NULL; gnb_lru32_node_t *pop_lru_node; gnb_doubly_linked_list_node_t *head_dl_node; if ( 0 == lru->size || NULL==lru->doubly_linked_list->head ) { return NULL; } pop_lru_node = (gnb_lru32_node_t *)lru->doubly_linked_list->head->data; if ( NULL==pop_lru_node ) { return NULL; } pop_udata = pop_lru_node->udata; gnb_kv32_t *kv32 = gnb_hash32_del(lru->lru_node_map, pop_lru_node->kv->key->data, pop_lru_node->kv->key->size); if (NULL!=kv32) { gnb_kv32_release(lru->lru_node_map,kv32); } gnb_lru32_node_fixed_pool_push(lru, pop_lru_node); head_dl_node = gnb_doubly_linked_list_pop_head(lru->doubly_linked_list); lru->size--; return pop_udata; } void* gnb_lru32_pop_tail(gnb_lru32_t *lru){ void *pop_udata = NULL; gnb_lru32_node_t *pop_lru_node; if ( 0 == lru->size || NULL==lru->doubly_linked_list->tail ) { return NULL; } gnb_doubly_linked_list_node_t *tail_dl_node; pop_lru_node = (gnb_lru32_node_t *)lru->doubly_linked_list->tail->data; if (NULL==pop_lru_node) { return NULL; } pop_udata = pop_lru_node->udata; gnb_kv32_t *kv32 = gnb_hash32_del(lru->lru_node_map, pop_lru_node->kv->key->data, pop_lru_node->kv->key->size); if (NULL!=kv32) { gnb_kv32_release(lru->lru_node_map,kv32); } gnb_lru32_node_fixed_pool_push(lru, pop_lru_node); tail_dl_node = gnb_doubly_linked_list_pop_tail(lru->doubly_linked_list); lru->size--; return pop_udata; } void* gnb_lru32_get_head(gnb_lru32_t *lru){ void *pop_udata = NULL; gnb_lru32_node_t *pop_lru_node; if ( 0 == lru->size || NULL==lru->doubly_linked_list->head ) { return NULL; } pop_lru_node = (gnb_lru32_node_t *)lru->doubly_linked_list->head->data; if ( NULL==pop_lru_node ) { return NULL; } pop_udata = pop_lru_node->udata; return pop_udata; } void* gnb_lru32_get_tail(gnb_lru32_t *lru){ void *pop_udata = NULL; gnb_lru32_node_t *pop_lru_node; if ( 0 == lru->size || NULL==lru->doubly_linked_list->tail ) { return NULL; } pop_lru_node = (gnb_lru32_node_t *)lru->doubly_linked_list->tail->data; if (NULL==pop_lru_node) { return NULL; } pop_udata = pop_lru_node->udata; return pop_udata; } opengnb-ver1.6.0.a/src/gnb_lru32.h000077500000000000000000000171501500454252100166440ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 . */ #ifndef GNB_LRU32_H #define GNB_LRU32_H #include #include #include "gnb_alloc.h" #include "gnb_fixed_pool.h" #include "gnb_hash32.h" #include "gnb_doubly_linked_list.h" typedef struct _gnb_lru32_t gnb_lru32_t; typedef struct _gnb_lru32_node_t gnb_lru32_node_t; typedef struct _gnb_lru32_node_t{ gnb_doubly_linked_list_node_t *dl_node; // dll_node->data -> gnb_lru32_node_t* gnb_kv32_t *kv; // 保存在 hashmap 中的kv,使得在双向链表这端可以通过key去存取 hashmap void *udata; // -> lru payload }gnb_lru32_node_t; typedef struct _gnb_lru32_t{ gnb_heap_t *heap; gnb_doubly_linked_list_t *doubly_linked_list; gnb_hash32_map_t *lru_node_map; //save type: gnb_lru32_node_t uint32_t size; uint32_t max_size; //lru 可以存数据的指针也可以申请一块内存把数据拷贝到该内存块 //存入的数据块的大小,如果为0,用同样的key每次set进去都要释放此前为存储数据块申请的内存, //如果不等于0,存入数据的时候就使用之前申请好的内存 uint32_t block_size; gnb_fixed_pool_t *lru_node_fixed_pool; gnb_fixed_pool_t *dl_node_fixed_pool; gnb_fixed_pool_t *udata_fixed_pool; }gnb_lru32_t; /* 如果用 gnb_lru32_set 和 gnb_lru32_store 保存 数据 到 lru, block_size 设为0 如果用 gnb_lru32_block_set 保存 数据 到 lru, block_size 设为 block 的大小,这对于保存一些容量相同的数据,可以避免频繁申请/释放内存 */ gnb_lru32_t *gnb_lru32_create(gnb_heap_t *heap, uint32_t max_size,uint32_t block_size); //需要释放完 lru 里的lru_node->udata,才能执行这个函数 //释放到操作是 迭代执行 gnb_lru32_pop_head 或 gnb_lru32_pop_tail,直到返回为NULL //由于lru_node->udata存放的是调用者的私有数据,因此释放时需要由调用者自行处理 void gnb_lru32_release(gnb_lru32_t *lru); //这个函数传入的 data 需要调用者申请内存和释放内存 //如果set入data前发现链表已经满了,就立即返回当前传入的data由调用者释放 //如果set入data后发现链表满了,就dropt掉tail,并返回tail的data由调用者释放 void* gnb_lru32_put(gnb_lru32_t *lru, unsigned char *key, uint32_t key_len, void *data); #define GNB_LRU32_PUT(lru,key,key_len,data) gnb_lru32_put(lru, (unsigned char *)key, (uint32_t)key_len, data) //传入的 data 会在 lru 内部申请一块内存,拷贝一份,当链表满了需要丢弃tail的节点时,tail节点绑定的这块内存也会被gnb_lru32_set释放 void gnb_lru32_store(gnb_lru32_t *lru, unsigned char *key, uint32_t key_len, void *data, uint32_t size); #define GNB_LRU32_STORE(lru,key,key_len,data,size) gnb_lru32_store(lru, (unsigned char *)key, (uint32_t)key_len, data, (uint32_t)size) //传入的data会拷贝到lru中一块内存里,相同的key存入数据会覆盖之前的数据, //每个key对应的内存块是预先申请好的,大小一致的,在调用gnb_lru32_creates时通过block_size设定 //用这个函数保存小块数据到lru是效率最高的,不需要频繁申请/释放内存 void gnb_lru32_fixed_store(gnb_lru32_t *lru, unsigned char *key, uint32_t key_len, void *data); #define GNB_LRU32_FIXED_STORE(lru,key,key_len,data) gnb_lru32_fixed_store(lru,(unsigned char *)key,(uint32_t)key_len, data) //这个函数不会把命中的节点移到链表首部,需要调用 gnb_lru32_movetohead 实现 gnb_lru32_node_t* gnb_lru32_hash_get(gnb_lru32_t *lru, unsigned char *key, uint32_t key_len); #define GNB_LRU32_HASH_GET(lru,key,key_len) gnb_lru32_hash_get(lru,key,(uint32_t)key_len); //如果命中,会调用 gnb_lru32_movetohead 把命中的节点移动到链表首部 gnb_lru32_node_t* gnb_lru32_get(gnb_lru32_t *lru, unsigned char *key, uint32_t key_len); #define GNB_LRU32_GET(lru,key,key_len) gnb_lru32_get(lru,key,(uint32_t)key_len); #define GNB_LRU32_VALUE(b) b!=NULL?b->udata:NULL #define GNB_LRU32_HASH_GET_VALUE(lru,key,key_len) GNB_LRU32_VALUE( gnb_lru32_hash_get(lru, (unsigned char *)key, (uint32_t)key_len) ) #define GNB_LRU32_GET_VALUE(lru,key,key_len) GNB_LRU32_VALUE( gnb_lru32_get(lru, (unsigned char *)key, (uint32_t)key_len) ) void gnb_lru32_movetohead(gnb_lru32_t *lru, unsigned char *key, uint32_t key_len); #define GNB_LRU32_MOVETOHEAD(lru,key,key_len) gnb_lru32_movetohead(lru, (unsigned char *)key, (uint32_t)key_len) void* gnb_lru32_pop_by_key(gnb_lru32_t *lru, unsigned char *key, uint32_t key_len); #define GNB_LRU32_POP_BY_KEY(lru,key,key_len) gnb_lru32_pop_by_key(lru,key,(uint32_t)key_len) void* gnb_lru32_pop_head(gnb_lru32_t *lru); void* gnb_lru32_pop_tail(gnb_lru32_t *lru); void* gnb_lru32_get_head(gnb_lru32_t *lru); void* gnb_lru32_get_tail(gnb_lru32_t *lru); #define GNB_LRU32_UINT32_PUT(lru,key,data) gnb_lru32_put(lru, (unsigned char *)(&key), sizeof(uint32_t), data) #define GNB_LRU32_UINT32_STORE(lru,key,data,size) gnb_lru32_store(lru, (unsigned char *)(&key), sizeof(uint32_t), data, (uint32_t)size) #define GNB_LRU32_UINT32_FIXED_STORE(lru,key,data) gnb_lru32_fixed_store(lru, (unsigned char *)(&key), sizeof(uint32_t), data) #define GNB_LRU32_UINT32_HASH_GET(lru,key) gnb_lru32_hash_get(lru,(unsigned char *)*&key),sizeof(uint32_t)); #define GNB_LRU32_UINT32_GET(lru,key) gnb_lru32_get(lru,(unsigned char *)(&key),sizeof(uint32_t)); #define GNB_LRU32_UINT32_POP_BY_KEY(lru,key) gnb_lru32_pop_by_key(lru, (unsigned char *)(&key), sizeof(uint32_t)) #define GNB_LRU32_UINT32_MOVETOHEAD(lru,key) gnb_lru32_movetohead(lru, (unsigned char *)(&key), sizeof(uint32_t)) #define GNB_LRU32_UINT32_HASH_GET_VALUE(lru,key) GNB_LRU32_VALUE( gnb_lru32_hash_get(lru, (unsigned char *)(&key), sizeof(uint32_t)) ) #define GNB_LRU32_UINT32_GET_VALUE(lru,key) GNB_LRU32_VALUE( gnb_lru32_get(lru, (unsigned char *)(&key), sizeof(uint32_t)) ) #define GNB_LRU32_UINT64_PUT(lru,key,data) gnb_lru32_put(lru, (unsigned char *)(&key), sizeof(uint64_t), data) #define GNB_LRU32_UINT64_STORE(lru,key,data,size) gnb_lru32_store(lru, (unsigned char *)(&key), sizeof(uint64_t), data, (uint32_t)size) #define GNB_LRU32_UINT64_FIXED_STORE(lru,key,data) gnb_lru32_fixed_store(lru, (unsigned char *)(&key), sizeof(uint64_t), data) #define GNB_LRU32_UINT64_HASH_GET(lru,key) gnb_lru32_hash_get(lru,(unsigned char *)*&key),sizeof(uint64_t)); #define GNB_LRU32_UINT64_GET(lru,key) gnb_lru32_get(lru,(unsigned char *)(&key),sizeof(uint64_t)); #define GNB_LRU32_UINT64_POP_BY_KEY(lru,key) gnb_lru32_pop_by_key(lru, (unsigned char *)(&key), sizeof(uint64_t)) #define GNB_LRU32_UINT64_MOVETOHEAD(lru,key) gnb_lru32_movetohead(lru, (unsigned char *)(&key), sizeof(uint64_t)) #define GNB_LRU32_UINT64_HASH_GET_VALUE(lru,key) GNB_LRU32_VALUE( gnb_lru32_hash_get(lru, (unsigned char *)(&key), sizeof(uint64_t)) ) #define GNB_LRU32_UINT64_GET_VALUE(lru,key) GNB_LRU32_VALUE( gnb_lru32_get(lru, (unsigned char *)(&key), sizeof(uint64_t)) ) #endif opengnb-ver1.6.0.a/src/gnb_mmap.c000077500000000000000000000132661500454252100166260ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 #include #include #include #if defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) || defined(__OpenBSD__) #define __UNIX_LIKE_OS__ 1 #endif #ifdef __UNIX_LIKE_OS__ #include #include #include #include #endif #ifdef _WIN32 #include #endif #include #include "gnb_mmap.h" typedef struct _gnb_mmap_block_t { #ifdef __UNIX_LIKE_OS__ int fd; #endif #ifdef _WIN32 HANDLE file_descriptor; HANDLE map_handle; #endif char filename[PATH_MAX]; void *block; size_t block_size; int mmap_type; }gnb_mmap_block_t; #ifdef __UNIX_LIKE_OS__ gnb_mmap_block_t* gnb_mmap_create(const char *filename, size_t block_size, int mmap_type){ gnb_mmap_block_t *mmap_block; int fd; void *block; int oflag; int prot; if ( (mmap_type & GNB_MMAP_TYPE_CREATE) && (mmap_type & GNB_MMAP_TYPE_READWRITE) ) { oflag = O_RDWR|O_CREAT; } else if (mmap_type & GNB_MMAP_TYPE_READWRITE) { oflag = O_RDWR; } else { oflag = O_RDONLY; } fd = open(filename, oflag, S_IRUSR|S_IWUSR); if ( -1 == fd ) { return NULL; } if ( mmap_type & GNB_MMAP_TYPE_CREATE) { if ( -1 == ftruncate(fd,block_size) ) { close(fd); return NULL; } } if ( mmap_type & GNB_MMAP_TYPE_READWRITE) { prot = PROT_READ|PROT_WRITE; } else { prot = PROT_READ; } block = mmap(NULL, block_size, prot, MAP_SHARED, fd, 0); if ( NULL==block ) { close(fd); return NULL; } mmap_block = (gnb_mmap_block_t *)malloc(sizeof(gnb_mmap_block_t)); snprintf(mmap_block->filename, PATH_MAX, "%s", filename); mmap_block->fd = fd; mmap_block->block = block; mmap_block->block_size = block_size; mmap_block->mmap_type = mmap_type; if ( mmap_type & GNB_MMAP_TYPE_CREATE ) { memset(mmap_block->block, 0, block_size); } return mmap_block; } void gnb_mmap_release(gnb_mmap_block_t *mmap_block){ munmap(mmap_block->block,mmap_block->block_size); close(mmap_block->fd); if ( mmap_block->mmap_type & (GNB_MMAP_TYPE_CREATE|GNB_MMAP_TYPE_CLEANEXIT) ) { unlink(mmap_block->filename); } free(mmap_block); } #endif #ifdef _WIN32 #include "gnb_binary.h" gnb_mmap_block_t* gnb_mmap_create(const char *filename, size_t block_size, int mmap_type){ char mapping_buffer[PATH_MAX]; char *mapping_name; void *block; mapping_name = gnb_bin2hex_string((void *)filename, strlen(filename), mapping_buffer); if ( NULL==mapping_name ) { return NULL; } gnb_mmap_block_t *mmap_block; int oflag1; int oflag2; int oflag3; int oflag4; int prot; if ( (mmap_type & GNB_MMAP_TYPE_CREATE) && (mmap_type & GNB_MMAP_TYPE_READWRITE) ) { oflag1 = GENERIC_READ | GENERIC_WRITE; oflag2 = FILE_SHARE_READ | FILE_SHARE_WRITE; oflag3 = OPEN_ALWAYS; oflag4 = PAGE_READWRITE; prot = FILE_MAP_WRITE | FILE_MAP_READ; } else if ( mmap_type & GNB_MMAP_TYPE_READWRITE ) { oflag1 = GENERIC_READ | GENERIC_WRITE; oflag2 = FILE_SHARE_READ | FILE_SHARE_WRITE; oflag3 = OPEN_EXISTING; oflag4 = PAGE_READWRITE; prot = FILE_MAP_WRITE | FILE_MAP_READ; } else { oflag1 = GENERIC_READ | GENERIC_WRITE; oflag2 = FILE_SHARE_READ | FILE_SHARE_WRITE; oflag3 = OPEN_EXISTING; oflag4 = PAGE_READWRITE; prot = FILE_MAP_READ; } HANDLE file_descriptor = CreateFile(filename, oflag1, oflag2, NULL, oflag3, FILE_ATTRIBUTE_NORMAL, NULL); if ( INVALID_HANDLE_VALUE == file_descriptor ) { return NULL; } HANDLE map_handle = CreateFileMapping( file_descriptor, NULL, oflag4, 0, block_size, mapping_name); if ( NULL == map_handle ) { return NULL; } block = MapViewOfFile(map_handle,prot,0,0,block_size); if ( NULL==block ) { CloseHandle(map_handle); CloseHandle(file_descriptor); return NULL; } mmap_block = (gnb_mmap_block_t *)malloc(sizeof(gnb_mmap_block_t)); snprintf(mmap_block->filename, PATH_MAX, "%s", filename); mmap_block->file_descriptor = file_descriptor; mmap_block->map_handle = map_handle; mmap_block->block = block; mmap_block->block_size = block_size; mmap_block->mmap_type = mmap_type; if ( mmap_type & GNB_MMAP_TYPE_CREATE ) { memset(mmap_block->block,0,block_size); } return mmap_block; } void gnb_mmap_release(gnb_mmap_block_t *mmap_block){ UnmapViewOfFile(mmap_block->block); CloseHandle(mmap_block->map_handle); CloseHandle(mmap_block->file_descriptor); free(mmap_block); } #endif void* gnb_mmap_get_block(gnb_mmap_block_t *mmap_block){ return mmap_block->block; } size_t gnb_mmap_get_size(gnb_mmap_block_t *mmap_block){ return mmap_block->block_size; } opengnb-ver1.6.0.a/src/gnb_mmap.h000077500000000000000000000023661500454252100166320ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 . */ #ifndef GNB_MMAP_H #define GNB_MMAP_H #include typedef struct _gnb_mmap_block_t gnb_mmap_block_t; #define GNB_MMAP_TYPE_READONLY (0x0) #define GNB_MMAP_TYPE_READWRITE (0x1) #define GNB_MMAP_TYPE_CREATE (0x1 << 1) #define GNB_MMAP_TYPE_CLEANEXIT (0x1 << 2) gnb_mmap_block_t* gnb_mmap_create(const char *filename, size_t block_size, int mmap_type); void gnb_mmap_release(gnb_mmap_block_t *mmap_block); void* gnb_mmap_get_block(gnb_mmap_block_t *mmap_block); size_t gnb_mmap_get_size(gnb_mmap_block_t *mmap_block); #endif opengnb-ver1.6.0.a/src/gnb_mod_register.c000077500000000000000000000025651500454252100203570ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 . */ /* 改名为 pf_register */ #include "gnb.h" #include "gnb_pf.h" extern gnb_pf_t gnb_pf_dump; extern gnb_pf_t gnb_pf_route; extern gnb_pf_t gnb_pf_crypto_xor; extern gnb_pf_t gnb_pf_crypto_arc4; extern gnb_pf_t gnb_pf_zip; gnb_pf_t *gnb_pf_mods[] = { &gnb_pf_dump, &gnb_pf_route, &gnb_pf_crypto_xor, &gnb_pf_crypto_arc4, &gnb_pf_zip, 0 }; gnb_pf_t* gnb_find_pf_mod_by_name(const char *name){ int num = sizeof(gnb_pf_mods)/sizeof(gnb_pf_t *); int i; for ( i=0; iname,name,128) ) { return gnb_pf_mods[i]; } } return NULL; } opengnb-ver1.6.0.a/src/gnb_node.c000077500000000000000000000644651500454252100166300ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 "gnb_node.h" #include #include #include #include #ifdef __UNIX_LIKE_OS__ #include #endif #ifdef _WIN32 #undef _WIN32_WINNT #define _WIN32_WINNT 0x0600 #include #include #endif #include "gnb_keys.h" #include "gnb_time.h" #include "gnb_udp.h" #include "gnb_hash32.h" #include "ed25519/ed25519.h" #include "ed25519/sha512.h" #include "gnb_unified_forwarding.h" #include "gnb_binary.h" gnb_node_t * gnb_node_init(gnb_core_t *gnb_core, gnb_uuid_t uuid64){ gnb_node_t *node = &gnb_core->ctl_block->node_zone->node[gnb_core->node_nums]; memset(node,0,sizeof(gnb_node_t)); node->uuid64 = uuid64; node->type = GNB_NODE_TYPE_STD; gnb_uuid_t node_id_network_order; gnb_uuid_t local_node_id_network_order; gnb_address_list_t *static_address_list; gnb_address_list_t *dynamic_address_list; gnb_address_list_t *resolv_address_list; gnb_address_list_t *push_address_list; gnb_address_list_t *detect_address_list; static_address_list = (gnb_address_list_t *)node->static_address_block; dynamic_address_list = (gnb_address_list_t *)node->dynamic_address_block; resolv_address_list = (gnb_address_list_t *)node->resolv_address_block; push_address_list = (gnb_address_list_t *)node->push_address_block; detect_address_list = (gnb_address_list_t *)node->detect_address4_block; static_address_list->size = GNB_NODE_STATIC_ADDRESS_NUM; dynamic_address_list->size = GNB_NODE_DYNAMIC_ADDRESS_NUM; resolv_address_list->size = GNB_NODE_RESOLV_ADDRESS_NUM; push_address_list->size = GNB_NODE_PUSH_ADDRESS_NUM; detect_address_list->size = 3; if ( 0 == gnb_core->conf->lite_mode ) { if ( gnb_core->conf->local_uuid != uuid64 ) { gnb_load_public_key(gnb_core, uuid64, node->public_key); ed25519_key_exchange(node->shared_secret, node->public_key, gnb_core->ed25519_private_key); } else { memcpy(node->public_key, gnb_core->ed25519_public_key, 32); memset(node->shared_secret, 0, 32); memset(node->crypto_key, 0, 64); } } else { //lite mode if ( gnb_core->conf->local_uuid == uuid64 ) { memset(gnb_core->ed25519_private_key, 0, 64); memset(gnb_core->ed25519_public_key, 0,32); } memset(node->public_key, 0, 32); node_id_network_order = gnb_htonll(uuid64); local_node_id_network_order = gnb_htonll(gnb_core->conf->local_uuid); memcpy(node->public_key, &node_id_network_order, 4); memset(node->shared_secret, 0, 32); memcpy(node->shared_secret, gnb_core->conf->crypto_passcode, 4); if ( node_id_network_order > local_node_id_network_order ) { memcpy(node->shared_secret+4, &node_id_network_order, 4); memcpy(node->shared_secret+8, &local_node_id_network_order, 4); } else { memcpy(node->shared_secret+4, &local_node_id_network_order, 4); memcpy(node->shared_secret+8, &node_id_network_order, 4); } } return node; } void gnb_init_node_key512(gnb_core_t *gnb_core){ int num = gnb_core->ctl_block->node_zone->node_num; int i; gnb_uuid_t uuid64; gnb_node_t *node; unsigned char buffer[32+4]; for (i=0;ictl_block->node_zone->node[i]; if ( NULL==node ) { continue; } memcpy(buffer, node->public_key,32); memcpy(buffer+32, gnb_core->conf->crypto_passcode, 4); sha512(buffer, 32+4, node->key512); } } void gnb_add_forward_node_ring(gnb_core_t *gnb_core, gnb_uuid_t uuid64){ gnb_node_t *node; node = GNB_HASH32_UINT64_GET_PTR(gnb_core->uuid_node_map, uuid64); if ( NULL == node ) { return; } if ( gnb_core->fwd_node_ring.num >= GNB_MAX_NODE_RING ) { gnb_core->fwd_node_ring.num = GNB_MAX_NODE_RING; return; } node->type |= GNB_NODE_TYPE_IDX; gnb_core->fwd_node_ring.nodes[gnb_core->fwd_node_ring.num] = node; gnb_core->fwd_node_ring.cur_index = gnb_core->fwd_node_ring.num; gnb_core->fwd_node_ring.num++; } void gnb_add_index_node_ring(gnb_core_t *gnb_core, gnb_uuid_t uuid64){ gnb_node_t *node; node = GNB_HASH32_UINT64_GET_PTR(gnb_core->uuid_node_map, uuid64); if ( NULL == node ) { return; } if ( gnb_core->index_node_ring.num >= GNB_MAX_NODE_RING ) { gnb_core->index_node_ring.num = GNB_MAX_NODE_RING; return; } node->type |= GNB_NODE_TYPE_IDX; gnb_core->index_node_ring.nodes[gnb_core->index_node_ring.num] = node; gnb_core->index_node_ring.cur_index = gnb_core->index_node_ring.num; gnb_core->index_node_ring.num++; } gnb_node_t* gnb_select_forward_node(gnb_core_t *gnb_core){ int i; gnb_node_t *node; if ( 0 == gnb_core->fwd_node_ring.num ) { return NULL; } if ( 1 == gnb_core->fwd_node_ring.num ) { return gnb_core->fwd_node_ring.nodes[0]; } if ( gnb_core->conf->pf_worker_num > 0 ) { return gnb_core->fwd_node_ring.nodes[0]; } if ( GNB_MULTI_ADDRESS_TYPE_SIMPLE_FAULT_TOLERANT == gnb_core->conf->multi_forward_type ) { goto SIMPLE_FAULT_TOLERANT; } if ( GNB_MULTI_ADDRESS_TYPE_SIMPLE_LOAD_BALANCE == gnb_core->conf->multi_forward_type ) { goto SIMPLE_LOAD_BALANCE; } SIMPLE_FAULT_TOLERANT: for ( i=0; ifwd_node_ring.num; i++ ) { if ( (GNB_NODE_STATUS_IPV6_PONG | GNB_NODE_STATUS_IPV4_PONG) & gnb_core->fwd_node_ring.nodes[i]->udp_addr_status ) { return gnb_core->fwd_node_ring.nodes[i]; } } return gnb_core->fwd_node_ring.nodes[0]; SIMPLE_LOAD_BALANCE: for ( i=0; ifwd_node_ring.num; i++ ) { node = gnb_core->fwd_node_ring.nodes[ gnb_core->fwd_node_ring.cur_index ]; if ( (GNB_NODE_STATUS_IPV6_PONG | GNB_NODE_STATUS_IPV4_PONG) & node->udp_addr_status ) { gnb_core->fwd_node_ring.cur_index++; if ( gnb_core->fwd_node_ring.cur_index >= gnb_core->fwd_node_ring.num ) { gnb_core->fwd_node_ring.cur_index = 0; } return node; } } return gnb_core->fwd_node_ring.nodes[0]; } void gnb_send_to_address(gnb_core_t *gnb_core, gnb_address_t *address, gnb_payload16_t *payload){ struct sockaddr_in in; struct sockaddr_in6 in6; if ( 0 == address->port ) { return; } if ( AF_INET6 == address->type ) { memset(&in6,0,sizeof(struct sockaddr_in6)); in6.sin6_family = AF_INET6; in6.sin6_port = address->port; memcpy(&in6.sin6_addr, address->address.addr6, 16); sendto(gnb_core->udp_ipv6_sockets[0], (void *)payload, GNB_PAYLOAD16_FRAME_SIZE(payload), 0, (struct sockaddr *)&in6, sizeof(struct sockaddr_in6) ); } if ( AF_INET == address->type ) { memset(&in,0,sizeof(struct sockaddr_in)); in.sin_family = AF_INET; in.sin_port = address->port; memcpy(&in.sin_addr, address->address.addr4, 4); sendto(gnb_core->udp_ipv4_sockets[0], (void *)payload, GNB_PAYLOAD16_FRAME_SIZE(payload), 0, (struct sockaddr *)&in, sizeof(struct sockaddr_in)); } } void gnb_send_udata_to_address(gnb_core_t *gnb_core, gnb_address_t *address, void *udata, size_t udata_size){ struct sockaddr_in in; struct sockaddr_in6 in6; if ( 0 == address->port ) { return; } if ( AF_INET6 == address->type ) { memset(&in6,0,sizeof(struct sockaddr_in6)); in6.sin6_family = AF_INET6; in6.sin6_port = address->port; memcpy(&in6.sin6_addr, address->address.addr6, 16); sendto(gnb_core->udp_ipv6_sockets[0], udata, udata_size, 0, (struct sockaddr *)&in6, sizeof(struct sockaddr_in6) ); } if ( AF_INET == address->type ) { memset(&in,0,sizeof(struct sockaddr_in)); in.sin_family = AF_INET; in.sin_port = address->port; memcpy(&in.sin_addr, address->address.addr4, 4); sendto(gnb_core->udp_ipv4_sockets[0], udata, udata_size, 0, (struct sockaddr *)&in, sizeof(struct sockaddr_in)); } } void gnb_send_address_list(gnb_core_t *gnb_core, gnb_address_list_t *address_list, gnb_payload16_t *payload){ int i; for ( i=0; inum; i++ ) { gnb_send_to_address(gnb_core, &address_list->array[i], payload); } } void gnb_send_available_address_list(gnb_core_t *gnb_core, gnb_address_list_t *address_list, gnb_payload16_t *payload, uint64_t now_sec){ int i; for ( i=0; inum; i++ ) { if ( now_sec - address_list->array[i].ts_sec > GNB_ADDRESS_LIFE_TIME_TS_SEC ) { continue; } gnb_send_to_address(gnb_core, &address_list->array[i], payload); } } void gnb_send_address_list_through_all_sockets(gnb_core_t *gnb_core, gnb_address_list_t *address_list, gnb_payload16_t *payload, uint32_t interval_usec){ int i; for ( i=0; inum; i++ ) { gnb_send_to_address_through_all_sockets(gnb_core, &address_list->array[i], payload, interval_usec); } } void gnb_send_to_address_through_all_sockets(gnb_core_t *gnb_core, gnb_address_t *address, gnb_payload16_t *payload, uint32_t interval_usec){ struct sockaddr_in in; struct sockaddr_in6 in6; if ( 0 == address->port ) { return; } int i; if ( AF_INET6 == address->type ) { memset(&in6,0,sizeof(struct sockaddr_in6)); in6.sin6_family = AF_INET6; in6.sin6_port = address->port; memcpy(&in6.sin6_addr, address->address.addr6, 16); for (i=0; iconf->udp6_socket_num; i++) { sendto(gnb_core->udp_ipv6_sockets[i], (void *)payload, GNB_PAYLOAD16_FRAME_SIZE(payload), 0, (struct sockaddr *)&in6, sizeof(struct sockaddr_in6) ); GNB_SLEEP_MILLISECOND( interval_usec/1000 ); } } if ( AF_INET == address->type ) { memset(&in,0,sizeof(struct sockaddr_in)); in.sin_family = AF_INET; in.sin_port = address->port; memcpy(&in.sin_addr, address->address.addr4, 4); for (i=0; iconf->udp4_socket_num; i++) { sendto(gnb_core->udp_ipv4_sockets[i], (void *)payload, GNB_PAYLOAD16_FRAME_SIZE(payload), 0, (struct sockaddr *)&in, sizeof(struct sockaddr_in)); GNB_SLEEP_MILLISECOND( interval_usec/1000 ); } } } gnb_address_t* gnb_select_index_address(gnb_core_t *gnb_core, uint64_t now_sec){ int i; gnb_address_t *gnb_address; if ( 0 == gnb_core->index_address_ring.address_list->num ) { return NULL; } if ( 1 == gnb_core->index_address_ring.address_list->num ) { return &gnb_core->index_address_ring.address_list->array[0]; } if ( GNB_MULTI_ADDRESS_TYPE_SIMPLE_FAULT_TOLERANT == gnb_core->conf->multi_index_type ) { goto SIMPLE_FAULT_TOLERANT; } if ( GNB_MULTI_ADDRESS_TYPE_SIMPLE_LOAD_BALANCE == gnb_core->conf->multi_index_type ) { goto SIMPLE_LOAD_BALANCE; } SIMPLE_FAULT_TOLERANT: for ( i=0; iindex_address_ring.address_list->num; i++ ) { gnb_address = &gnb_core->index_address_ring.address_list->array[i]; if ( !(gnb_core->conf->udp_socket_type & GNB_ADDR_TYPE_IPV4) && ( AF_INET6 == gnb_address->type) ) { continue; } if ( GNB_ADDRESS_AVAILABLE(gnb_address, now_sec) ) { return &gnb_core->index_address_ring.address_list->array[i]; } } return &gnb_core->index_address_ring.address_list->array[0]; SIMPLE_LOAD_BALANCE: for ( i=0; iindex_address_ring.address_list->num; i++ ) { gnb_address = &gnb_core->index_address_ring.address_list->array[ gnb_core->index_address_ring.cur_index ]; gnb_core->index_address_ring.cur_index++; if ( gnb_core->index_address_ring.cur_index >= gnb_core->index_address_ring.address_list->num ) { gnb_core->index_address_ring.cur_index = 0; } if ( !(gnb_core->conf->udp_socket_type & GNB_ADDR_TYPE_IPV4) && ( AF_INET6 == gnb_address->type) ) { continue; } if ( GNB_ADDRESS_AVAILABLE(gnb_address,now_sec) ) { return gnb_address; } } return &gnb_core->index_address_ring.address_list->array[0]; } gnb_node_t* gnb_select_index_nodes(gnb_core_t *gnb_core){ int i; gnb_node_t *gnb_index_node; if ( 0 == gnb_core->index_node_ring.num ) { return NULL; } if ( 1 == gnb_core->index_node_ring.num ) { return gnb_core->index_node_ring.nodes[0]; } if ( GNB_MULTI_ADDRESS_TYPE_SIMPLE_FAULT_TOLERANT == gnb_core->conf->multi_index_type ) { goto SIMPLE_FAULT_TOLERANT; } if ( GNB_MULTI_ADDRESS_TYPE_SIMPLE_LOAD_BALANCE == gnb_core->conf->multi_index_type ) { goto SIMPLE_LOAD_BALANCE; } SIMPLE_FAULT_TOLERANT: for ( i=0; iindex_node_ring.num; i++ ) { gnb_index_node = gnb_core->index_node_ring.nodes[i]; if ( GNB_NODE_STATUS_IPV6_PONG & gnb_index_node->udp_addr_status || GNB_NODE_STATUS_IPV4_PONG & gnb_index_node->udp_addr_status ) { return gnb_core->index_node_ring.nodes[i]; } } return gnb_core->index_node_ring.nodes[0]; SIMPLE_LOAD_BALANCE: for ( i=0; iindex_node_ring.num; i++ ) { gnb_index_node = gnb_core->index_node_ring.nodes[gnb_core->index_node_ring.cur_index]; gnb_core->index_node_ring.cur_index++; if ( gnb_core->index_node_ring.cur_index >= gnb_core->index_node_ring.num ) { gnb_core->index_node_ring.cur_index = 0; } if ( GNB_NODE_STATUS_IPV6_PONG & gnb_index_node->udp_addr_status || GNB_NODE_STATUS_IPV4_PONG & gnb_index_node->udp_addr_status ) { return gnb_core->index_node_ring.nodes[i]; } } return gnb_core->index_node_ring.nodes[0]; } gnb_address_t* gnb_select_available_address4(gnb_core_t *gnb_core, gnb_node_t *node){ gnb_address_t *address = NULL; int i; gnb_address_list_t *address_list; address_list = (gnb_address_list_t *)&node->push_address_block; for ( i=0; inum; i++ ) { if ( AF_INET != address_list->array[i].type ) { continue; } if ( 0 == address_list->array[i].port ) { continue; } //如果存在多个地址,选择更新时间是最新的 if ( NULL != address ) { if ( address->ts_sec > address_list->array[i].ts_sec ) { continue; } } address = &address_list->array[i]; } if ( NULL != address ) { goto finish; } address_list = (gnb_address_list_t *)&node->dynamic_address_block; for ( i=0; inum; i++ ) { if ( AF_INET != address_list->array[i].type ) { continue; } if ( 0 == address_list->array[i].port ) { continue; } //如果存在多个地址,选择更新时间是最新的 if ( NULL != address ) { if ( address_list->array[i].ts_sec > address->ts_sec ) { continue; } } address = &address_list->array[i]; } if ( NULL != address ) { goto finish; } address_list = (gnb_address_list_t *)&node->resolv_address_block; for ( i=0; inum; i++ ) { if ( AF_INET != address_list->array[i].type ) { continue; } if ( 0 == address_list->array[i].port ) { continue; } //如果存在多个地址,选择更新时间是最新的 if ( NULL != address ) { if ( address_list->array[i].ts_sec > address->ts_sec ) { continue; } } address = &address_list->array[i]; } if ( NULL != address ) { goto finish; } address_list = (gnb_address_list_t *)&node->static_address_block; for ( i=0; inum; i++ ) { if ( AF_INET != address_list->array[i].type ) { continue; } if ( 0 == address_list->array[i].port ) { continue; } address = &address_list->array[i]; break; } finish: return address; } int gnb_send_to_node(gnb_core_t *gnb_core, gnb_node_t *node, gnb_payload16_t *payload, unsigned char addr_type_bits){ if ( GNB_ADDR_TYPE_IPV6 == gnb_core->conf->udp_socket_type ) { goto send_by_ipv6; } int i; if ( (GNB_ADDR_TYPE_IPV4 & addr_type_bits) && (gnb_core->conf->udp_socket_type & GNB_ADDR_TYPE_IPV4) && INADDR_ANY != node->udp_sockaddr4.sin_addr.s_addr ) { for (i=0; iconf->udp4_socket_num; i++) { sendto(gnb_core->udp_ipv4_sockets[ i ], (void *)payload, GNB_PAYLOAD16_FRAME_SIZE(payload), 0, (struct sockaddr *)&node->udp_sockaddr4, sizeof(struct sockaddr_in)); } } if ( GNB_ADDR_TYPE_IPV4 == gnb_core->conf->udp_socket_type ) { goto finish; } send_by_ipv6: if ( (GNB_ADDR_TYPE_IPV6 & addr_type_bits) && (gnb_core->conf->udp_socket_type & GNB_ADDR_TYPE_IPV6) > 0 && memcmp(&node->udp_sockaddr6.sin6_addr,&in6addr_any,sizeof(struct in6_addr)) ) { for (i=0; iconf->udp6_socket_num; i++) { sendto(gnb_core->udp_ipv6_sockets[i],(void *)payload, GNB_PAYLOAD16_FRAME_SIZE(payload), 0, (struct sockaddr *)&node->udp_sockaddr6, sizeof(struct sockaddr_in6) ); } } finish: return 0; } int gnb_p2p_forward_payload_to_node(gnb_core_t *gnb_core, gnb_node_t *node, gnb_payload16_t *payload){ int ret; // gnb_core->conf->udp_socket_type 默认是 GNB_ADDR_TYPE_IPV4 | GNB_ADDR_TYPE_IPV6; if ( GNB_ADDR_TYPE_IPV4 == gnb_core->conf->udp_socket_type ) { goto send_by_ipv4; } else if ( GNB_ADDR_TYPE_IPV6 == gnb_core->conf->udp_socket_type ) { goto send_by_ipv6; } if ( (node->udp_addr_status & GNB_NODE_STATUS_IPV6_PONG) && (node->udp_addr_status & GNB_NODE_STATUS_IPV4_PONG) ) { if ( 0 == node->addr4_ping_latency_usec ) { goto send_by_ipv6; } if ( 0 == node->addr6_ping_latency_usec ) { goto send_by_ipv4; } if ( node->addr4_ping_latency_usec >= node->addr6_ping_latency_usec ) { goto send_by_ipv6; } else { goto send_by_ipv4; } } send_by_ipv6: if ( (node->udp_addr_status & GNB_NODE_STATUS_IPV6_PONG) && (gnb_core->conf->udp_socket_type & GNB_ADDR_TYPE_IPV6) && memcmp(&node->udp_sockaddr6.sin6_addr,&in6addr_any,sizeof(struct in6_addr)) ) { sendto(gnb_core->udp_ipv6_sockets[node->socket6_idx],(void *)payload, GNB_PAYLOAD16_FRAME_SIZE(payload), 0, (struct sockaddr *)&node->udp_sockaddr6, sizeof(struct sockaddr_in6) ); goto finish; } send_by_ipv4: ret = sendto(gnb_core->udp_ipv4_sockets[ node->socket4_idx ], (void *)payload, GNB_PAYLOAD16_FRAME_SIZE(payload), 0, (struct sockaddr *)&node->udp_sockaddr4, sizeof(struct sockaddr_in)); finish: return 0; } #define GNB_SEND_BY_UNSET (0x0) #define GNB_SEND_BY_P2P_IPV6 (0x1) #define GNB_SEND_BY_P2P_IPV4 (0x2) #define GNB_SEND_BY_FWD_IPV6 (0x3) #define GNB_SEND_BY_FWD_IPV4 (0x4) void gnb_std_uf_forward_payload_to_node(gnb_core_t *gnb_core, gnb_node_t *node, gnb_payload16_t *payload){ int ret; int send_flag = GNB_SEND_BY_UNSET; gnb_node_t *fwd_node; if ( (node->udp_addr_status & GNB_NODE_STATUS_IPV6_PONG) && (node->udp_addr_status & GNB_NODE_STATUS_IPV4_PONG) ) { if ( 0 == node->addr4_ping_latency_usec ) { send_flag = GNB_SEND_BY_P2P_IPV6; goto p2p_forwarding; } if ( 0 == node->addr6_ping_latency_usec ) { send_flag = GNB_SEND_BY_P2P_IPV4; goto p2p_forwarding; } if ( node->addr4_ping_latency_usec >= node->addr6_ping_latency_usec ) { send_flag = GNB_SEND_BY_P2P_IPV6; goto p2p_forwarding; } else { send_flag = GNB_SEND_BY_P2P_IPV4; goto p2p_forwarding; } } else if ( (node->udp_addr_status & GNB_NODE_STATUS_IPV6_PONG) && (GNB_ADDR_TYPE_IPV6 & gnb_core->conf->udp_socket_type) ) { send_flag = GNB_SEND_BY_P2P_IPV6; } else if ( (node->udp_addr_status & GNB_NODE_STATUS_IPV4_PONG) && (GNB_ADDR_TYPE_IPV4 & gnb_core->conf->udp_socket_type) ) { send_flag = GNB_SEND_BY_P2P_IPV4; } else { send_flag = GNB_SEND_BY_UNSET; goto try_to_standard_forwarding; } p2p_forwarding: if ( GNB_SEND_BY_P2P_IPV6 == send_flag ) { if ( memcmp(&node->udp_sockaddr6.sin6_addr, &in6addr_any,sizeof(struct in6_addr)) ) { return; } sendto(gnb_core->udp_ipv6_sockets[node->socket6_idx],(void *)payload, GNB_PAYLOAD16_FRAME_SIZE(payload), 0, (struct sockaddr *)&node->udp_sockaddr6, sizeof(struct sockaddr_in6) ); return; } else if ( GNB_SEND_BY_P2P_IPV4 == send_flag ) { if ( INADDR_ANY == node->udp_sockaddr4.sin_addr.s_addr ) { return; } sendto(gnb_core->udp_ipv4_sockets[node->socket4_idx], (void *)payload, GNB_PAYLOAD16_FRAME_SIZE(payload), 0, (struct sockaddr *)&node->udp_sockaddr4, sizeof(struct sockaddr_in)); return; } try_to_standard_forwarding: //如果无法 point to point forwarding 就尝试通过 standard forwarding 节点转发 fwd_node = gnb_select_forward_node(gnb_core); if ( NULL == fwd_node ) { goto try_to_unified_forwarding; } if ( (fwd_node->udp_addr_status & GNB_NODE_STATUS_IPV6_PONG) && (fwd_node->udp_addr_status & GNB_NODE_STATUS_IPV4_PONG) ) { if ( 0 == fwd_node->addr4_ping_latency_usec ) { send_flag = GNB_SEND_BY_FWD_IPV6; goto standard_forwarding; } if ( 0 == fwd_node->addr6_ping_latency_usec ) { send_flag = GNB_SEND_BY_FWD_IPV4; goto standard_forwarding; } if ( fwd_node->addr4_ping_latency_usec >= fwd_node->addr6_ping_latency_usec ) { send_flag = GNB_SEND_BY_FWD_IPV6; goto standard_forwarding; } else { send_flag = GNB_SEND_BY_FWD_IPV4; goto standard_forwarding; } } else if ( (fwd_node->udp_addr_status & GNB_NODE_STATUS_IPV6_PONG) && (GNB_ADDR_TYPE_IPV6 & gnb_core->conf->udp_socket_type) ) { send_flag = GNB_SEND_BY_FWD_IPV6; } else if ( (fwd_node->udp_addr_status & GNB_NODE_STATUS_IPV4_PONG) && (GNB_ADDR_TYPE_IPV4 & gnb_core->conf->udp_socket_type) ) { send_flag = GNB_SEND_BY_FWD_IPV4; } else { send_flag = GNB_SEND_BY_UNSET; goto try_to_unified_forwarding; } standard_forwarding: if ( GNB_SEND_BY_FWD_IPV6 == send_flag ) { if ( memcmp(&fwd_node->udp_sockaddr6.sin6_addr, &in6addr_any,sizeof(struct in6_addr)) ) { return; } sendto(gnb_core->udp_ipv6_sockets[fwd_node->socket6_idx],(void *)payload, GNB_PAYLOAD16_FRAME_SIZE(payload), 0, (struct sockaddr *)&fwd_node->udp_sockaddr6, sizeof(struct sockaddr_in6) ); return; } else if ( GNB_SEND_BY_FWD_IPV4 == send_flag ) { if ( INADDR_ANY == fwd_node->udp_sockaddr4.sin_addr.s_addr ) { return; } sendto(gnb_core->udp_ipv4_sockets[fwd_node->socket4_idx], (void *)payload, GNB_PAYLOAD16_FRAME_SIZE(payload), 0, (struct sockaddr *)&fwd_node->udp_sockaddr4, sizeof(struct sockaddr_in)); return; } try_to_unified_forwarding: //如果无法 standard forwarding 就尝试通过 unified forwarding 节点转发 gnb_setup_unified_forwarding_nodeid(gnb_core, node); if ( 0 == node->unified_forwarding_nodeid ) { return; } fwd_node = GNB_HASH32_UINT64_GET_PTR(gnb_core->uuid_node_map, node->unified_forwarding_nodeid); if ( NULL == fwd_node ) { return; } //如果对端的fwd_node 关闭了 std forwarding, payload 转过去后会被 drop 掉 if ( (fwd_node->udp_addr_status & GNB_NODE_STATUS_IPV6_PONG) && (fwd_node->udp_addr_status & GNB_NODE_STATUS_IPV4_PONG) ) { if ( 0 == fwd_node->addr4_ping_latency_usec ) { send_flag = GNB_SEND_BY_FWD_IPV6; goto unified_forwarding; } if ( 0 == fwd_node->addr6_ping_latency_usec ) { send_flag = GNB_SEND_BY_FWD_IPV4; goto unified_forwarding; } if ( fwd_node->addr4_ping_latency_usec >= fwd_node->addr6_ping_latency_usec ) { send_flag = GNB_SEND_BY_FWD_IPV6; goto unified_forwarding; } else { send_flag = GNB_SEND_BY_FWD_IPV4; goto unified_forwarding; } } else if ( (fwd_node->udp_addr_status & GNB_NODE_STATUS_IPV6_PONG) && (GNB_ADDR_TYPE_IPV6 & gnb_core->conf->udp_socket_type) ) { send_flag = GNB_SEND_BY_FWD_IPV6; } else if ( (fwd_node->udp_addr_status & GNB_NODE_STATUS_IPV4_PONG) && (GNB_ADDR_TYPE_IPV4 & gnb_core->conf->udp_socket_type) ) { send_flag = GNB_SEND_BY_FWD_IPV4; } else { send_flag = GNB_SEND_BY_UNSET; } unified_forwarding: if ( GNB_SEND_BY_FWD_IPV6 == send_flag ) { if ( memcmp(&fwd_node->udp_sockaddr6.sin6_addr,&in6addr_any,sizeof(struct in6_addr)) ) { return; } sendto(gnb_core->udp_ipv6_sockets[fwd_node->socket6_idx],(void *)payload, GNB_PAYLOAD16_FRAME_SIZE(payload), 0, (struct sockaddr *)&fwd_node->udp_sockaddr6, sizeof(struct sockaddr_in6) ); return; } else if ( GNB_SEND_BY_FWD_IPV4 == send_flag ) { if ( INADDR_ANY == fwd_node->udp_sockaddr4.sin_addr.s_addr ) { return; } sendto(gnb_core->udp_ipv4_sockets[fwd_node->socket4_idx], (void *)payload, GNB_PAYLOAD16_FRAME_SIZE(payload), 0, (struct sockaddr *)&fwd_node->udp_sockaddr4, sizeof(struct sockaddr_in)); return; } return; } opengnb-ver1.6.0.a/src/gnb_node.h000077500000000000000000000045711500454252100166250ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 . */ #ifndef GNB_NODE_H #define GNB_NODE_H #include "gnb.h" void gnb_init_node_key512(gnb_core_t *gnb_core); void gnb_add_forward_node_ring(gnb_core_t *gnb_core, gnb_uuid_t uuid64); void gnb_add_index_node_ring(gnb_core_t *gnb_core, gnb_uuid_t uuid64); gnb_node_t* gnb_select_forward_node(gnb_core_t *gnb_core); int gnb_node_sign_verify(gnb_core_t *gnb_core, gnb_uuid_t uuid64, unsigned char *sign, void *data, size_t data_size); void gnb_send_to_address(gnb_core_t *gnb_core, gnb_address_t *address, gnb_payload16_t *payload); void gnb_send_udata_to_address(gnb_core_t *gnb_core, gnb_address_t *address, void *udata, size_t udata_size); void gnb_send_address_list(gnb_core_t *gnb_core, gnb_address_list_t *address_list, gnb_payload16_t *payload); void gnb_send_to_address_through_all_sockets(gnb_core_t *gnb_core, gnb_address_t *address, gnb_payload16_t *payload, uint32_t interval_usec); void gnb_send_address_list_through_all_sockets(gnb_core_t *gnb_core, gnb_address_list_t *address_list, gnb_payload16_t *payload, uint32_t interval_usec); void gnb_send_available_address_list(gnb_core_t *gnb_core, gnb_address_list_t *address_list, gnb_payload16_t *payload, uint64_t now_sec); gnb_address_t* gnb_select_index_address(gnb_core_t *gnb_core, uint64_t now_sec); gnb_node_t* gnb_select_index_nodes(gnb_core_t *gnb_core); gnb_address_t* gnb_select_available_address4(gnb_core_t *gnb_core, gnb_node_t *node); int gnb_send_to_node(gnb_core_t *gnb_core, gnb_node_t *node, gnb_payload16_t *payload, unsigned char addr_type_bits); int gnb_p2p_forward_payload_to_node(gnb_core_t *gnb_core, gnb_node_t *node, gnb_payload16_t *payload); void gnb_std_uf_forward_payload_to_node(gnb_core_t *gnb_core, gnb_node_t *node, gnb_payload16_t *payload); #endif opengnb-ver1.6.0.a/src/gnb_node_type.h000077500000000000000000000140431500454252100176610ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 . */ #ifndef GNB_NODE_TYPE_H #define GNB_NODE_TYPE_H #include #include "gnb_address_type.h" #include "gnb_type.h" typedef struct _gnb_unified_forwarding_node_t { gnb_uuid_t uuid64; uint64_t last_ts_sec; }gnb_unified_forwarding_node_t; typedef struct _gnb_node_t{ gnb_uuid_t uuid64; uint64_t in_bytes; uint64_t out_bytes; #define GNB_NODE_TYPE_STD (0x0) #define GNB_NODE_TYPE_IDX (0x1) #define GNB_NODE_TYPE_FWD (0x1 << 1) #define GNB_NODE_TYPE_RELAY (0x1 << 2) #define GNB_NODE_TYPE_SLIENCE (0x1 << 3) #define GNB_NODE_TYPE_STATIC_ADDR (0x1 << 4) //未使用 #define GNB_NODE_TYPE_DYNAMIC_ADDR (0x1 << 5) unsigned char type; struct in_addr tun_addr4; struct in_addr tun_netmask_addr4; struct in_addr tun_subnet_addr4; uint16_t tun_sin_port4; struct in6_addr tun_ipv6_addr; struct sockaddr_in udp_sockaddr4; struct sockaddr_in6 udp_sockaddr6; uint8_t socket6_idx; uint8_t socket4_idx; #define GNB_MAX_NODE_ROUTE 8 #define GNB_MAX_NODE_RELAY 5 gnb_uuid_t route_node[GNB_MAX_NODE_ROUTE][GNB_MAX_NODE_RELAY]; uint8_t route_node_ttls[GNB_MAX_NODE_ROUTE]; uint8_t selected_route_node; #define GNB_NODE_RELAY_DISABLE (0x0) #define GNB_NODE_RELAY_AUTO (0x1) #define GNB_NODE_RELAY_FORCE (0x1 << 1) #define GNB_NODE_RELAY_STATIC (0x1 << 2) #define GNB_NODE_RELAY_BALANCE (0x1 << 3) uint8_t node_relay_mode; #define GNB_NODE_STATIC_ADDRESS_NUM 6 #define GNB_NODE_DYNAMIC_ADDRESS_NUM 16 #define GNB_NODE_RESOLV_ADDRESS_NUM 6 #define GNB_NODE_PUSH_ADDRESS_NUM 6 //静态地址,来自 address.conf 不更新,send_detect_addr_frame 时使用 unsigned char static_address_block[sizeof(gnb_address_list_t) + sizeof(gnb_address_t)*GNB_NODE_STATIC_ADDRESS_NUM]; //在 handle_detect_addr_frame 中更新,send_detect_addr_frame 时使用 unsigned char dynamic_address_block[sizeof(gnb_address_list_t) + sizeof(gnb_address_t)*GNB_NODE_DYNAMIC_ADDRESS_NUM]; //通过 address.conf 中的域名异步更新这个表,send_detect_addr_frame 时使用 unsigned char resolv_address_block[sizeof(gnb_address_list_t) + sizeof(gnb_address_t)*GNB_NODE_RESOLV_ADDRESS_NUM]; //handle_push_addr_frame时更新, 及在启动时加载自文件缓存 unsigned char push_address_block[sizeof(gnb_address_list_t) + sizeof(gnb_address_t)*GNB_NODE_PUSH_ADDRESS_NUM]; unsigned char available_address6_list3_block[sizeof(gnb_address_list_t) + sizeof(gnb_address_t)*3]; unsigned char available_address4_list3_block[sizeof(gnb_address_list_t) + sizeof(gnb_address_t)*3]; unsigned char detect_address4_block[sizeof(gnb_address_list_t) + sizeof(gnb_address_t)*3]; uint8_t detect_address4_idx; struct in_addr detect_addr4; uint16_t detect_port4; #define GNB_NODE_MAX_DETECT_TIMES 32 uint32_t detect_count; //上次发对该node发送 ping 的时间戳,不区分ipv4和ipv6 uint64_t ping_ts_sec; uint64_t ping_ts_usec; #define GNB_NODE_STATUS_UNREACHABL (0x0) #define GNB_NODE_STATUS_IPV4_PING (0x1) #define GNB_NODE_STATUS_IPV6_PING (0x1 << 1) #define GNB_NODE_STATUS_IPV4_PONG (0x1 << 2) #define GNB_NODE_STATUS_IPV6_PONG (0x1 << 3) #define GNB_NODE_STATUS_IPV4_STATIC (0x1 << 2) #define GNB_NODE_STATUS_IPV6_STATIC (0x1 << 3) //初始值为 GNB_NODE_STATUS_UNREACHABL, 实现ping pong 后用 GNB_NODE_STATUS_IPV4 GNB_NODE_STATUS_IPV6 置位 unsigned int udp_addr_status; int64_t addr6_ping_latency_usec; int64_t addr4_ping_latency_usec; //上次node发来 ping4 或 pong4 时间戳 uint64_t addr4_update_ts_sec; //上次node发来 ping6 或 pong6 时间戳 uint64_t addr6_update_ts_sec; //ed25519 public key unsigned char public_key[32]; //ed25519 或 通过 passcode 产生的 share key unsigned char shared_secret[32]; //shared_secret 与 gnb_core->time_seed & 运算后再经过 sha512 的摘要信息 unsigned char crypto_key[64]; //当前通信密钥 //由于 crypto_key 可以随时间变更,通信密钥在更换瞬间有一定概率会出现用新密钥解密对端发来的数据 //保留上一个的旧通信密钥,用于解密旧密钥加密的数据,当前支持 ur1 freame unsigned char pre_crypto_key[64]; //上一个通信密钥 unsigned char key512[64]; gnb_uuid_t last_relay_nodeid; #define GNB_LAST_RELAY_NODE_EXPIRED_SEC 145 uint64_t last_relay_node_ts_sec; gnb_uuid_t unified_forwarding_nodeid; #define GNB_UNIFIED_FORWARDING_NODE_EXPIRED_SEC 15 uint64_t unified_forwarding_node_ts_sec; #define GNB_UNIFIED_FORWARDING_NODE_ARRAY_EXPIRED_SEC 90 #define GNB_UNIFIED_FORWARDING_NODE_ARRAY_SIZE 32 gnb_unified_forwarding_node_t unified_forwarding_node_array[GNB_UNIFIED_FORWARDING_NODE_ARRAY_SIZE]; uint64_t unified_forwarding_send_seq; uint64_t unified_forwarding_recv_seq; #define UNIFIED_FORWARDING_RECV_SEQ_ARRAY_SIZE 32 uint64_t unified_forwarding_recv_seq_array[UNIFIED_FORWARDING_RECV_SEQ_ARRAY_SIZE]; uint64_t last_notify_uf_nodes_ts_sec; //上次向 index 节点查询的时间戳 uint64_t last_request_addr_sec; uint64_t last_push_addr_sec; uint64_t last_detect_sec; uint64_t last_send_detect_usec; uint64_t last_full_detect_sec; }gnb_node_t; #define GNB_MAX_NODE_RING 128 typedef struct _gnb_node_ring_t{ int num; int cur_index; gnb_node_t *nodes[GNB_MAX_NODE_RING]; }gnb_node_ring_t; #endif opengnb-ver1.6.0.a/src/gnb_node_worker.c000077500000000000000000001042371500454252100202110ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 #include #ifdef _WIN32 #define _POSIX #define __USE_MINGW_ALARM #endif #include #include #include #include #include #include #include "gnb.h" #include "gnb_time.h" #include "gnb_keys.h" #include "gnb_node.h" #include "gnb_worker.h" #include "gnb_ring_buffer_fixed.h" #include "gnb_worker_queue_data.h" #include "gnb_pingpong_frame_type.h" #include "gnb_uf_node_frame_type.h" #include "gnb_unified_forwarding.h" #include "ed25519/ed25519.h" //节点同步检测的时间间隔 #define GNB_NODE_SYNC_INTERVAL_TIME_SEC 10 //对一个node的ping时间间隔 #define GNB_NODE_PING_INTERVAL_SEC 37 //对于一个节点必须收到的 ping 或 pong 的时间间隔 #define GNB_NODE_UPDATE_INTERVAL_SEC (GNB_NODE_PING_INTERVAL_SEC * 2 + 1) #define GNB_UF_NODES_NOTIFY_INTERVAL_SEC 35 typedef struct _node_worker_ctx_t { gnb_core_t *gnb_core; gnb_payload16_t *node_frame_payload; uint64_t now_time_usec; uint64_t now_time_sec; uint64_t last_sync_ts_sec; pthread_t thread_worker; }node_worker_ctx_t; void update_node_crypto_key(gnb_core_t *gnb_core, uint64_t now_sec); static void update_unified_forwarding_node_array(gnb_core_t *gnb_core, gnb_node_t *node, gnb_node_t *uf_node) { int i; int find_idx = -1; int pop_idx = 0; uint64_t last_ts_sec = 0l; node_worker_ctx_t *node_worker_ctx = gnb_core->node_worker->ctx; for ( i=0; iunified_forwarding_node_array[i].uuid64 ) { find_idx = i; break; } if ( uf_node->uuid64 == node->unified_forwarding_node_array[i].uuid64 ) { find_idx = i; break; } if ( (node_worker_ctx->now_time_sec - node->unified_forwarding_node_array[i].last_ts_sec) > GNB_UNIFIED_FORWARDING_NODE_ARRAY_EXPIRED_SEC ) { find_idx = i; break; } if ( node->unified_forwarding_node_array[i].last_ts_sec > last_ts_sec ) { last_ts_sec = node->unified_forwarding_node_array[i].last_ts_sec; pop_idx = i; } } if ( -1 == find_idx ) { find_idx = pop_idx; } node->unified_forwarding_node_array[find_idx].uuid64 = uf_node->uuid64; node->unified_forwarding_node_array[find_idx].last_ts_sec = node_worker_ctx->now_time_sec; } static void handle_uf_node_notify_frame(gnb_core_t *gnb_core, gnb_worker_in_data_t *node_worker_in_data){ gnb_worker_t *primary_worker = gnb_core->primary_worker; node_worker_ctx_t *node_worker_ctx = gnb_core->node_worker->ctx; uf_node_notify_frame_t *uf_node_notify_frame = (uf_node_notify_frame_t *)&node_worker_in_data->payload_st.data; gnb_uuid_t src_uuid64 = gnb_ntohll(uf_node_notify_frame->data.src_uuid64); gnb_uuid_t dst_uuid64 = gnb_ntohll(uf_node_notify_frame->data.dst_uuid64); gnb_uuid_t df_uuid64 = gnb_ntohll(uf_node_notify_frame->data.df_uuid64); gnb_sockaddress_t *node_addr = &node_worker_in_data->node_addr_st; if ( src_uuid64 == gnb_core->local_node->uuid64 || dst_uuid64 != gnb_core->local_node->uuid64 || df_uuid64 == gnb_core->local_node->uuid64 ) { GNB_LOG2(gnb_core->log, GNB_LOG_ID_NODE_WORKER, "handle_uf_node_notify_frame error local=%llu src=%llu dst=%llu\n", gnb_core->local_node->uuid64, src_uuid64, dst_uuid64); return; } gnb_node_t *src_node = GNB_HASH32_UINT64_GET_PTR(gnb_core->uuid_node_map, src_uuid64); if ( NULL==src_node ) { GNB_LOG2(gnb_core->log, GNB_LOG_ID_NODE_WORKER, "handle_uf_node_notify_frame src node=%llu is miss\n", src_uuid64); return; } if ( 0 == gnb_core->conf->lite_mode && !ed25519_verify(uf_node_notify_frame->src_sign, (const unsigned char *)&uf_node_notify_frame->data, sizeof(struct uf_node_notify_frame_data), src_node->public_key) ) { GNB_LOG2(gnb_core->log, GNB_LOG_ID_NODE_WORKER, "handle_uf_node_notify_frame invalid signature src=%llu %s\n", src_uuid64, GNB_SOCKETADDRSTR1(node_addr)); return; } gnb_node_t *df_node = GNB_HASH32_UINT64_GET_PTR(gnb_core->uuid_node_map, df_uuid64); if ( NULL==df_node ) { GNB_LOG2(gnb_core->log, GNB_LOG_ID_NODE_WORKER, "handle_uf_node_notify_frame df node=%llu is miss\n", df_uuid64); return; } GNB_LOG2(gnb_core->log, GNB_LOG_ID_NODE_WORKER, "handle_uf_node_notify_frame src_uuid64=%llu dst_uuid64=%llu df_uuid64=%llu\n", src_uuid64, dst_uuid64, df_uuid64); update_unified_forwarding_node_array(gnb_core, df_node, src_node); } static void send_uf_node_notify_frame(gnb_core_t *gnb_core, gnb_node_t *dst_node, gnb_node_t *direct_forwarding_node){ gnb_worker_t *primary_worker = gnb_core->primary_worker; node_worker_ctx_t *node_worker_ctx = gnb_core->node_worker->ctx; node_worker_ctx->node_frame_payload->sub_type = PAYLOAD_SUB_TYPE_NODE_UNIFIED_NOTIFY; gnb_payload16_set_data_len(node_worker_ctx->node_frame_payload, sizeof(uf_node_notify_frame_t)); uf_node_notify_frame_t *uf_node_notify_frame = (uf_node_notify_frame_t *)node_worker_ctx->node_frame_payload->data; memset(uf_node_notify_frame, 0, sizeof(uf_node_notify_frame_t)); uf_node_notify_frame->data.src_uuid64 = gnb_htonll(gnb_core->local_node->uuid64); uf_node_notify_frame->data.dst_uuid64 = gnb_htonll(dst_node->uuid64); uf_node_notify_frame->data.df_uuid64 = gnb_htonll(direct_forwarding_node->uuid64); snprintf((char *)uf_node_notify_frame->data.text, 64, "UNIFIED_NOTIFY src=%llu dst=%llu df=%llu", gnb_core->local_node->uuid64, dst_node->uuid64, direct_forwarding_node->uuid64); if ( 0 == gnb_core->conf->lite_mode ) { ed25519_sign(uf_node_notify_frame->src_sign, (const unsigned char *)&uf_node_notify_frame->data, sizeof(struct uf_node_notify_frame_data), gnb_core->ed25519_public_key, gnb_core->ed25519_private_key); } gnb_p2p_forward_payload_to_node(gnb_core, dst_node, node_worker_ctx->node_frame_payload); GNB_LOG2(gnb_core->log, GNB_LOG_ID_NODE_WORKER, "send_uf_node_notify_frame src=%llu notify=%llu direct_forwarding=%llu\n", gnb_core->local_node->uuid64, dst_node->uuid64, direct_forwarding_node->uuid64); } static void unifield_forwarding_notify(gnb_core_t *gnb_core, gnb_node_t *dst_node){ size_t num = gnb_core->ctl_block->node_zone->node_num; if ( 0 == num ) { return; } int i; gnb_node_t *df_node; for ( i=0; ictl_block->node_zone->node[i]; if ( dst_node->uuid64 == df_node->uuid64 ) { continue; } if ( gnb_core->local_node->uuid64 == df_node->uuid64 ) { continue; } if ( !( (GNB_NODE_STATUS_IPV6_PONG | GNB_NODE_STATUS_IPV4_PONG) & df_node->udp_addr_status ) ) { continue; } send_uf_node_notify_frame(gnb_core, dst_node, df_node); } } static void send_ping_frame(gnb_core_t *gnb_core, gnb_node_t *node){ int ret; gnb_worker_t *primary_worker = gnb_core->primary_worker; node_worker_ctx_t *node_worker_ctx = gnb_core->node_worker->ctx; if ( INADDR_ANY == node->udp_sockaddr4.sin_addr.s_addr && 0 == memcmp(&node->udp_sockaddr6.sin6_addr,&in6addr_any,sizeof(struct in6_addr)) ) { return; } if ( GNB_NODE_STATUS_UNREACHABL == node->udp_addr_status ) { if ( !(node->type & GNB_NODE_TYPE_IDX) && !(node->type & GNB_NODE_TYPE_FWD) && !(node->type & GNB_NODE_TYPE_RELAY) && !(node->type & GNB_NODE_TYPE_STATIC_ADDR) ) { return; } } node_worker_ctx->node_frame_payload->sub_type = PAYLOAD_SUB_TYPE_PING; gnb_payload16_set_data_len(node_worker_ctx->node_frame_payload, sizeof(node_ping_frame_t)); node_ping_frame_t *node_ping_frame = (node_ping_frame_t *)node_worker_ctx->node_frame_payload->data; memset(node_ping_frame, 0, sizeof(node_ping_frame_t)); node_ping_frame->data.src_uuid64 = gnb_htonll(gnb_core->local_node->uuid64); node_ping_frame->data.dst_uuid64 = gnb_htonll(node->uuid64); node_ping_frame->data.src_ts_usec = gnb_htonll(node_worker_ctx->now_time_usec); snprintf((char *)node_ping_frame->data.text, 32, "%llu --PING-> %llu", gnb_core->local_node->uuid64, node->uuid64); if ( 0 == gnb_core->conf->lite_mode ) { ed25519_sign(node_ping_frame->src_sign, (const unsigned char *)&node_ping_frame->data, sizeof(struct ping_frame_data), gnb_core->ed25519_public_key, gnb_core->ed25519_private_key); } //PING frame 尽可能 ipv4 和 ipv6 都发送 gnb_send_to_node(gnb_core, node, node_worker_ctx->node_frame_payload, GNB_ADDR_TYPE_IPV6|GNB_ADDR_TYPE_IPV4); //更新 node 的ping 时间戳 node->ping_ts_sec = node_worker_ctx->now_time_sec; node->ping_ts_usec = node_worker_ctx->now_time_usec; GNB_LOG3(gnb_core->log,GNB_LOG_ID_NODE_WORKER, "ping src[%llu]->dst[%llu] %s %s ping_ts=%"PRIu64"\n", gnb_core->local_node->uuid64, node->uuid64, GNB_SOCKADDR6STR1(&node->udp_sockaddr6), GNB_SOCKADDR4STR2(&node->udp_sockaddr4), node->ping_ts_usec ); } static void handle_ping_frame(gnb_core_t *gnb_core, gnb_worker_in_data_t *node_worker_in_data){ gnb_worker_t *primary_worker = gnb_core->primary_worker; node_worker_ctx_t *node_worker_ctx = gnb_core->node_worker->ctx; node_ping_frame_t *node_ping_frame = (node_ping_frame_t *)&node_worker_in_data->payload_st.data; gnb_uuid_t src_uuid64 = gnb_ntohll(node_ping_frame->data.src_uuid64); gnb_uuid_t dst_uuid64 = gnb_ntohll(node_ping_frame->data.dst_uuid64); //收到ping frame,需要更新node的addr gnb_sockaddress_t *node_addr = &node_worker_in_data->node_addr_st; uint8_t addr_update = 0; if (src_uuid64 == gnb_core->local_node->uuid64) { //目标节点和当前节点在同一个子网里,当前节点发 ping frame 经过路由的nat又转回给了当前节点 GNB_LOG3(gnb_core->log, GNB_LOG_ID_NODE_WORKER, "handle_ping_frame local_node[%llu] src[%llu]=>dst[%llu]\n", gnb_core->local_node->uuid64, src_uuid64, dst_uuid64); return; } gnb_node_t *src_node = GNB_HASH32_UINT64_GET_PTR(gnb_core->uuid_node_map, src_uuid64); if ( NULL==src_node ) { GNB_LOG3(gnb_core->log, GNB_LOG_ID_NODE_WORKER, "handle_ping_frame error node=%llu is miss\n", src_uuid64); return; } if ( src_node->type & GNB_NODE_TYPE_SLIENCE ) { return; } //本地节点如果有 GNB_NODE_TYPE_SLIENCE 属性 将只响应 带有 GNB_NODE_TYPE_FWD 属性的节点 if ( (gnb_core->local_node->type & GNB_NODE_TYPE_SLIENCE) && !(src_node->type & GNB_NODE_TYPE_FWD) ) { return; } if ( 0 == gnb_core->conf->lite_mode && !ed25519_verify(node_ping_frame->src_sign, (const unsigned char *)&node_ping_frame->data, sizeof(struct ping_frame_data), src_node->public_key) ) { GNB_LOG3(gnb_core->log, GNB_LOG_ID_NODE_WORKER, "handle_ping_frame error invalid signature src=%llu text[%.*s] %s\n", src_uuid64, 32, node_ping_frame->data.text, GNB_SOCKETADDRSTR1(node_addr)); return; } uint64_t src_ts_usec = gnb_ntohll(node_ping_frame->data.src_ts_usec); int64_t latency_usec = node_worker_ctx->now_time_usec - src_ts_usec; if ( AF_INET6 == node_addr->addr_type ) { if ( 0 != gnb_determine_subnet6_prefixlen96(node_addr->addr.in6.sin6_addr, gnb_core->local_node->tun_ipv6_addr ) ) { GNB_LOG3(gnb_core->log,GNB_LOG_ID_NODE_WORKER, "handle_ping_frame IPV6 Warning src[%llu]->dst[%llu] idx=%u %s\n", src_node->uuid64, dst_uuid64, node_worker_in_data->socket_idx, GNB_ADDR6STR1(&node_addr->addr.in6.sin6_addr) ); return; } //只在发生改变的时候才更新 if ( 0 != gnb_cmp_sockaddr_in6(&src_node->udp_sockaddr6, &node_addr->addr.in6) || node_worker_in_data->socket_idx != src_node->socket6_idx ) { src_node->udp_sockaddr6 = node_addr->addr.in6; src_node->socket6_idx = node_worker_in_data->socket_idx; addr_update = 1; } src_node->udp_addr_status |= GNB_NODE_STATUS_IPV6_PING; src_node->addr6_update_ts_sec = node_worker_ctx->now_time_sec; GNB_LOG3(gnb_core->log,GNB_LOG_ID_NODE_WORKER, "handle_ping_frame IPV6 src[%llu]->dst[%llu] idx=%u %s now=%"PRIu64" src_ts=%"PRIu64" up=%u different=%"PRId64"\n", src_node->uuid64, dst_uuid64, node_worker_in_data->socket_idx, GNB_SOCKADDR6STR1(&src_node->udp_sockaddr6), node_worker_ctx->now_time_usec, src_ts_usec, addr_update, latency_usec); } if ( AF_INET == node_addr->addr_type ) { if ( 0 != gnb_determine_subnet4(node_addr->addr.in.sin_addr, gnb_core->local_node->tun_addr4, gnb_core->local_node->tun_netmask_addr4) ) { GNB_LOG3(gnb_core->log,GNB_LOG_ID_NODE_WORKER, "handle_ping_frame IPV4 Warning src[%llu]->dst[%llu] idx=%u %s\n", src_node->uuid64, dst_uuid64, node_worker_in_data->socket_idx, GNB_ADDR4STR1(&node_addr->addr.in.sin_addr) ); return; } //只在发生改变的时候才更新 if ( PAYLOAD_SUB_TYPE_PING == node_worker_in_data->payload_st.sub_type && (0 != gnb_cmp_sockaddr_in(&src_node->udp_sockaddr4, &node_addr->addr.in) || node_worker_in_data->socket_idx != src_node->socket4_idx) ) { src_node->udp_sockaddr4 = node_addr->addr.in; src_node->socket4_idx = node_worker_in_data->socket_idx; addr_update = 1; } //处理来自 LAN 的 ping frame if ( PAYLOAD_SUB_TYPE_LAN_PING == node_worker_in_data->payload_st.sub_type ) { src_node->udp_sockaddr4 = node_addr->addr.in; //LAN ping 的端口存放在 attachment 中 memcpy(&src_node->udp_sockaddr4.sin_port, node_ping_frame->data.attachment, sizeof(uint16_t)); src_node->socket4_idx = node_worker_in_data->socket_idx; addr_update = 1; GNB_LOG3(gnb_core->log, GNB_LOG_ID_NODE_WORKER, "handle_ping_frame IPV4 LAN src[%llu]->dst[%llu] idx=%u %s now=%"PRIu64" src_ts=%"PRIu64" up=%u different=%"PRId64"\n", src_node->uuid64, dst_uuid64, node_worker_in_data->socket_idx, GNB_SOCKADDR4STR1(&src_node->udp_sockaddr4), node_worker_ctx->now_time_usec, src_ts_usec, addr_update, latency_usec); } src_node->udp_addr_status |= GNB_NODE_STATUS_IPV4_PING; src_node->addr4_update_ts_sec = node_worker_ctx->now_time_sec; GNB_LOG3(gnb_core->log,GNB_LOG_ID_NODE_WORKER, "handle_ping_frame IPV4 src[%llu]->dst[%llu] idx=%u %s now=%"PRIu64" src_ts=%"PRIu64" up=%u different=%"PRId64"\n", src_node->uuid64, dst_uuid64, node_worker_in_data->socket_idx, GNB_SOCKADDR4STR1(&src_node->udp_sockaddr4), node_worker_ctx->now_time_usec, src_ts_usec, addr_update, latency_usec); } node_worker_ctx->node_frame_payload->sub_type = PAYLOAD_SUB_TYPE_PONG; gnb_payload16_set_data_len(node_worker_ctx->node_frame_payload, sizeof(node_pong_frame_t)); node_pong_frame_t *node_pong_frame = (node_pong_frame_t *)node_worker_ctx->node_frame_payload->data; memset(node_pong_frame, 0, sizeof(node_pong_frame_t)); node_pong_frame->data.src_uuid64 = gnb_htonll(gnb_core->local_node->uuid64); node_pong_frame->data.dst_uuid64 = gnb_htonll(src_node->uuid64); node_pong_frame->data.src_ts_usec = gnb_htonll(node_worker_ctx->now_time_usec); node_pong_frame->data.dst_ts_usec = node_ping_frame->data.src_ts_usec; //把本节点的 upd 端口 发送给对端,这个端口在节点连通的情况下用虚拟ip访问到 gnb_payload16_t *payload_attachment = (gnb_payload16_t *)node_pong_frame->data.attachment; gnb_payload16_set_data_len(payload_attachment, sizeof(node_attachment_tun_sockaddress_t)); payload_attachment->type = GNB_NODE_ATTACHMENT_TYPE_TUN_SOCKADDRESS; node_attachment_tun_sockaddress_t *attachment_tun_sockaddress = (node_attachment_tun_sockaddress_t *)payload_attachment->data; memcpy(&attachment_tun_sockaddress->tun_addr4, &gnb_core->local_node->tun_addr4.s_addr, 4); attachment_tun_sockaddress->tun_sin_port4 = gnb_core->local_node->tun_sin_port4; snprintf((char *)node_pong_frame->data.text,32,"%llu --PONG-> %llu",gnb_core->local_node->uuid64,src_node->uuid64); if ( 0 == gnb_core->conf->lite_mode ) { ed25519_sign(node_pong_frame->src_sign, (const unsigned char *)&node_pong_frame->data, sizeof(struct pong_frame_data), gnb_core->ed25519_public_key, gnb_core->ed25519_private_key); } unsigned char addr_type_bits; //根据源地址选择发送的类型 if ( AF_INET == node_addr->addr_type ) { addr_type_bits = GNB_ADDR_TYPE_IPV4; } if ( AF_INET6 == node_addr->addr_type ) { addr_type_bits = GNB_ADDR_TYPE_IPV6; } gnb_send_to_node(gnb_core, src_node, node_worker_ctx->node_frame_payload, addr_type_bits); } static void handle_pong_frame(gnb_core_t *gnb_core, gnb_worker_in_data_t *node_worker_in_data){ node_worker_ctx_t *node_worker_ctx = gnb_core->node_worker->ctx; node_pong_frame_t *node_pong_frame = (node_pong_frame_t *)&node_worker_in_data->payload_st.data; gnb_uuid_t src_uuid64 = gnb_ntohll(node_pong_frame->data.src_uuid64); gnb_uuid_t dst_uuid64 = gnb_ntohll(node_pong_frame->data.dst_uuid64); uint64_t dst_ts_usec = gnb_ntohll(node_pong_frame->data.dst_ts_usec); //收到pong frame,需要更新node的addr gnb_sockaddress_t *node_addr = &node_worker_in_data->node_addr_st; gnb_address_t address_st; gnb_address_list_t *address_list3; uint8_t addr_update = 0; if ( dst_uuid64 != gnb_core->local_node->uuid64 ) { GNB_LOG3(gnb_core->log,GNB_LOG_ID_NODE_WORKER, "handle_pong_frame dst_uuid64[%llu] != local_node[%llu] addr_type=%d\n", dst_uuid64, gnb_core->local_node->uuid64, node_worker_in_data->node_addr_st.addr_type); return; } gnb_node_t *src_node = GNB_HASH32_UINT64_GET_PTR(gnb_core->uuid_node_map, src_uuid64); if ( NULL==src_node ) { GNB_LOG3(gnb_core->log,GNB_LOG_ID_NODE_WORKER, "handle_pong_frame error node=%llu is miss\n", src_uuid64); return; } if ( src_node->type & GNB_NODE_TYPE_SLIENCE ) { return; } //本地节点如果有 GNB_NODE_TYPE_SLIENCE 属性 将只响应 带有 GNB_NODE_TYPE_FWD 属性的节点 if ( (gnb_core->local_node->type & GNB_NODE_TYPE_SLIENCE) && !(src_node->type & GNB_NODE_TYPE_FWD) ) { return; } if ( 0 == gnb_core->conf->lite_mode && !ed25519_verify(node_pong_frame->src_sign, (const unsigned char *)&node_pong_frame->data, sizeof(struct pong_frame_data), src_node->public_key) ) { GNB_LOG3(gnb_core->log, GNB_LOG_ID_NODE_WORKER, "handle_pong_frame error node=%llu invalid signature text[%.*s] %s\n", src_uuid64, 32, node_pong_frame->data.text, GNB_SOCKETADDRSTR1(node_addr)); return; } if ( node_worker_ctx->now_time_usec > dst_ts_usec ) { address_st.latency_usec = node_worker_ctx->now_time_usec - dst_ts_usec; } else { address_st.latency_usec = 1; } if ( AF_INET6 == node_addr->addr_type ) { if ( 0 != gnb_determine_subnet6_prefixlen96(node_addr->addr.in6.sin6_addr, gnb_core->local_node->tun_ipv6_addr ) ) { GNB_LOG3(gnb_core->log, GNB_LOG_ID_NODE_WORKER, "handle_pong_frame IPV6 Warning src[%llu]->dst[%llu] idx=%u %s\n", src_node->uuid64, dst_uuid64, node_worker_in_data->socket_idx, GNB_ADDR6STR1(&node_addr->addr.in6.sin6_addr) ); return; } src_node->udp_addr_status |= GNB_NODE_STATUS_IPV6_PONG; gnb_set_address6(&address_st, &node_addr->addr.in6); address_st.ts_sec = node_worker_ctx->now_time_sec; address_list3 = (gnb_address_list_t *)src_node->available_address6_list3_block; gnb_address_list3_fifo(address_list3, &address_st); //只在发生改变的时候才更新 if ( 0 != gnb_cmp_sockaddr_in6(&src_node->udp_sockaddr6, &node_addr->addr.in6) || node_worker_in_data->socket_idx != src_node->socket6_idx ) { src_node->udp_sockaddr6 = node_addr->addr.in6; src_node->socket6_idx = node_worker_in_data->socket_idx; addr_update = 1; } src_node->addr6_update_ts_sec = node_worker_ctx->now_time_sec; if ( dst_ts_usec == src_node->ping_ts_usec ) { src_node->addr6_ping_latency_usec = node_worker_ctx->now_time_usec - dst_ts_usec + 1; if ( 0 == src_node->addr6_ping_latency_usec ) { GNB_LOG3(gnb_core->log, GNB_LOG_ID_NODE_WORKER, "addr6_ping_latency_usec==0 now=%"PRIu64" dst_ts=%"PRIu64"\n", node_worker_ctx->now_time_usec, dst_ts_usec); } } GNB_LOG3(gnb_core->log, GNB_LOG_ID_NODE_WORKER, "handle_pong_frame IPV6 src[%llu]->dst[%llu] idx=%u %s now=%"PRIu64" dst_ts=%"PRIu64" up=%u latency=%"PRId64"\n", src_node->uuid64, dst_uuid64, node_worker_in_data->socket_idx, GNB_SOCKADDR6STR1(&src_node->udp_sockaddr6), node_worker_ctx->now_time_usec, dst_ts_usec, addr_update, src_node->addr6_ping_latency_usec); } if ( AF_INET == node_addr->addr_type ) { if ( 0 != gnb_determine_subnet4(node_addr->addr.in.sin_addr, gnb_core->local_node->tun_addr4, gnb_core->local_node->tun_netmask_addr4) ) { GNB_LOG3(gnb_core->log, GNB_LOG_ID_NODE_WORKER, "handle_pong_frame IPV4 Warning src[%llu]->dst[%llu] idx=%u %s\n", src_node->uuid64, dst_uuid64, node_worker_in_data->socket_idx, GNB_ADDR4STR1(&node_addr->addr.in.sin_addr) ); return; } src_node->udp_addr_status |= GNB_NODE_STATUS_IPV4_PONG; gnb_set_address4(&address_st, &node_addr->addr.in); address_st.ts_sec = node_worker_ctx->now_time_sec; address_list3 = (gnb_address_list_t *)src_node->available_address4_list3_block; gnb_address_list3_fifo(address_list3, &address_st); //只在发生改变的时候才更新 if ( 0 != gnb_cmp_sockaddr_in(&src_node->udp_sockaddr4, &node_addr->addr.in) || node_worker_in_data->socket_idx != src_node->socket4_idx ) { src_node->udp_sockaddr4 = node_addr->addr.in; src_node->socket4_idx = node_worker_in_data->socket_idx; addr_update = 1; } src_node->addr4_update_ts_sec = node_worker_ctx->now_time_sec; if ( dst_ts_usec == src_node->ping_ts_usec ) { src_node->addr4_ping_latency_usec = node_worker_ctx->now_time_usec - dst_ts_usec + 1; if ( 0 == src_node->addr4_ping_latency_usec ) { GNB_LOG3(gnb_core->log, GNB_LOG_ID_NODE_WORKER, "addr4_ping_latency_usec=0 now=%"PRIu64" dst_ts=%"PRIu64"\n", node_worker_ctx->now_time_usec, dst_ts_usec); } } GNB_LOG3(gnb_core->log, GNB_LOG_ID_NODE_WORKER, "handle_pong_frame IPV4 src[%llu]->dst[%llu] idx=%u %s now=%"PRIu64" dst_ts=%"PRIu64" up=%u latency=%"PRId64"\n", src_node->uuid64, dst_uuid64, node_worker_in_data->socket_idx, GNB_SOCKADDR4STR1(&src_node->udp_sockaddr4), node_worker_ctx->now_time_usec, dst_ts_usec, addr_update, src_node->addr4_ping_latency_usec); } //处理附件 gnb_payload16_t *payload_attachment = (gnb_payload16_t *)node_pong_frame->data.attachment; node_attachment_tun_sockaddress_t *attachment_tun_sockaddress; if ( GNB_NODE_ATTACHMENT_TYPE_TUN_SOCKADDRESS == payload_attachment->type ) { attachment_tun_sockaddress = (node_attachment_tun_sockaddress_t *)payload_attachment->data; if ( src_node->tun_sin_port4 != attachment_tun_sockaddress->tun_sin_port4 ) { src_node->tun_sin_port4 = attachment_tun_sockaddress->tun_sin_port4; } } if ( PAYLOAD_SUB_TYPE_PONG2 == node_worker_in_data->payload_st.sub_type ) { GNB_LOG3(gnb_core->log,GNB_LOG_ID_NODE_WORKER, "handle_pong2_frame src[%llu]->dst[%llu] idx=%u\n", src_node->uuid64, dst_uuid64, node_worker_in_data->socket_idx); return; } node_worker_ctx->node_frame_payload->sub_type = PAYLOAD_SUB_TYPE_PONG2; gnb_payload16_set_data_len(node_worker_ctx->node_frame_payload, sizeof(node_pong_frame_t)); node_pong_frame_t *node_pong2_frame = (node_pong_frame_t *)node_worker_ctx->node_frame_payload->data; memset(node_pong2_frame,0,sizeof(node_pong_frame_t)); node_pong2_frame->data.src_uuid64 = gnb_htonll(gnb_core->local_node->uuid64); node_pong2_frame->data.dst_uuid64 = gnb_htonll(src_node->uuid64); node_pong2_frame->data.src_ts_usec = gnb_htonll(node_worker_ctx->now_time_usec); node_pong2_frame->data.dst_ts_usec = node_pong2_frame->data.src_ts_usec; gnb_payload16_t *payload_attachment2 = (gnb_payload16_t *)node_pong2_frame->data.attachment; gnb_payload16_set_data_len(payload_attachment2, 0); payload_attachment2->type = GNB_NODE_ATTACHMENT_TYPE_TUN_EMPTY; snprintf((char *)node_pong2_frame->data.text,32,"%llu --PONG2-> %llu",gnb_core->local_node->uuid64,src_node->uuid64); if ( 0 == gnb_core->conf->lite_mode ) { ed25519_sign(node_pong2_frame->src_sign, (const unsigned char *)&node_pong2_frame->data, sizeof(struct pong_frame_data), gnb_core->ed25519_public_key, gnb_core->ed25519_private_key); } unsigned char addr_type_bits; //根据源地址选择发送的类型 if ( AF_INET == node_addr->addr_type ) { addr_type_bits = GNB_ADDR_TYPE_IPV4; } if ( AF_INET6 == node_addr->addr_type ) { addr_type_bits = GNB_ADDR_TYPE_IPV6; } gnb_send_to_node(gnb_core, src_node, node_worker_ctx->node_frame_payload, addr_type_bits); } static void sync_node(gnb_worker_t *gnb_node_worker){ node_worker_ctx_t *node_worker_ctx = gnb_node_worker->ctx; gnb_core_t *gnb_core = node_worker_ctx->gnb_core; size_t num = gnb_core->ctl_block->node_zone->node_num; if ( 0 == num ) { return; } int i; gnb_node_t *node; for ( i=0; ictl_block->node_zone->node[i]; if ( gnb_core->local_node->uuid64 == node->uuid64 ) { continue; } if ( node->type & GNB_NODE_TYPE_SLIENCE ) { continue; } //如果本地节点带有 GNB_NODE_TYPE_SLIENCE 属性 将只请求带有 GNB_NODE_TYPE_FWD 属性的节点的地址 if ( (gnb_core->local_node->type & GNB_NODE_TYPE_SLIENCE) && !(node->type & GNB_NODE_TYPE_FWD) ) { continue; } if( INADDR_ANY==node->udp_sockaddr4.sin_addr.s_addr && 0 == memcmp(&node->udp_sockaddr6.sin6_addr,&in6addr_any,sizeof(struct in6_addr)) && gnb_core->index_address_ring.address_list->num > 0 ) { if ( (node_worker_ctx->now_time_sec - node->ping_ts_sec) >= GNB_NODE_PING_INTERVAL_SEC ) { //如果地址为 0.0.0.0 或 :: , 需要向 index node 发送 PAYLOAD_SUB_TYPE_ADDR_QUERY node->udp_addr_status = GNB_NODE_STATUS_UNREACHABL; node->ping_ts_sec = node_worker_ctx->now_time_sec; } continue; } if ( (node_worker_ctx->now_time_sec - node->ping_ts_sec) >= GNB_NODE_PING_INTERVAL_SEC ) { send_ping_frame(gnb_core, node); } if ( GNB_UNIFIED_FORWARDING_OFF != gnb_core->conf->unified_forwarding && (node_worker_ctx->now_time_sec - node->last_notify_uf_nodes_ts_sec) >= GNB_UF_NODES_NOTIFY_INTERVAL_SEC ) { if ( !( (GNB_NODE_STATUS_IPV6_PONG | GNB_NODE_STATUS_IPV4_PONG) & node->udp_addr_status ) ) { continue; } GNB_LOG3(gnb_core->log, GNB_LOG_ID_NODE_WORKER, "unifield_forwarding_notify nodeid=%llu\n", node->uuid64); unifield_forwarding_notify(gnb_core, node); node->last_notify_uf_nodes_ts_sec = node_worker_ctx->now_time_sec; } if ( (node_worker_ctx->now_time_sec - node->addr4_update_ts_sec) > GNB_NODE_UPDATE_INTERVAL_SEC ) { //节点状态超时,且不是idx node, 可能目标node已经下线或者更换了ip //IPV4 需要向 idx node 发送 PAYLOAD_SUB_TYPE_ADDR_QUERY if ( !(node->type & GNB_NODE_TYPE_IDX) ) { node->udp_addr_status &= ~(GNB_NODE_STATUS_IPV4_PONG | GNB_NODE_STATUS_IPV4_PING); } } if ( (node_worker_ctx->now_time_sec - node->addr6_update_ts_sec) > GNB_NODE_UPDATE_INTERVAL_SEC ) { //节点状态超时,且不是idx node, 可能目标node已经下线或者更换了ip if ( !(node->type & GNB_NODE_TYPE_IDX) ) { node->udp_addr_status &= ~(GNB_NODE_STATUS_IPV6_PONG | GNB_NODE_STATUS_IPV6_PING); } } } } static void handle_node_frame(gnb_core_t *gnb_core, gnb_worker_in_data_t *node_worker_in_data){ gnb_payload16_t *payload = &node_worker_in_data->payload_st; if ( GNB_PAYLOAD_TYPE_NODE != payload->type ) { GNB_LOG2(gnb_core->log, GNB_LOG_ID_NODE_WORKER, "handle_node_frame GNB_PAYLOAD_TYPE_NODE != payload->type[%x]\n", payload->type); return; } switch ( payload->sub_type ) { case PAYLOAD_SUB_TYPE_PING: case PAYLOAD_SUB_TYPE_LAN_PING: handle_ping_frame(gnb_core, node_worker_in_data); break; case PAYLOAD_SUB_TYPE_PONG : case PAYLOAD_SUB_TYPE_PONG2 : handle_pong_frame(gnb_core, node_worker_in_data); break; case PAYLOAD_SUB_TYPE_NODE_UNIFIED_NOTIFY: handle_uf_node_notify_frame(gnb_core, node_worker_in_data); break; default: break; } return; } static void handle_recv_queue(gnb_core_t *gnb_core){ int i; node_worker_ctx_t *node_worker_ctx = gnb_core->node_worker->ctx; gnb_worker_queue_data_t *receive_queue_data; int ret; for ( i=0; i<1024; i++ ) { receive_queue_data = gnb_ring_buffer_fixed_pop( gnb_core->node_worker->ring_buffer_in ); if ( NULL == receive_queue_data) { break; } handle_node_frame(gnb_core, &receive_queue_data->data.node_in); gnb_ring_buffer_fixed_pop_submit( gnb_core->node_worker->ring_buffer_in ); } } static void* thread_worker_func( void *data ) { gnb_worker_t *gnb_node_worker = (gnb_worker_t *)data; node_worker_ctx_t *node_worker_ctx = gnb_node_worker->ctx; gnb_core_t *gnb_core = node_worker_ctx->gnb_core; gnb_node_worker->thread_worker_flag = 1; gnb_node_worker->thread_worker_run_flag = 1; gnb_worker_wait_primary_worker_started(gnb_core); GNB_LOG1(gnb_core->log, GNB_LOG_ID_NODE_WORKER, "start %s success!\n", gnb_node_worker->name); do{ gnb_worker_sync_time(&node_worker_ctx->now_time_sec, &node_worker_ctx->now_time_usec); update_node_crypto_key(gnb_core, node_worker_ctx->now_time_sec); handle_recv_queue(gnb_core); //每经过一个时间间隔就检查一次各节点的状态 if ( node_worker_ctx->now_time_sec - node_worker_ctx->last_sync_ts_sec > GNB_NODE_SYNC_INTERVAL_TIME_SEC ) { sync_node(gnb_node_worker); node_worker_ctx->last_sync_ts_sec = node_worker_ctx->now_time_sec; } GNB_SLEEP_MILLISECOND(150); }while(gnb_node_worker->thread_worker_flag); gnb_node_worker->thread_worker_run_flag = 0; return NULL; } static void init(gnb_worker_t *gnb_worker, void *ctx){ gnb_core_t *gnb_core = (gnb_core_t *)ctx; void *memory; size_t memory_size; node_worker_ctx_t *node_worker_ctx = (node_worker_ctx_t *)gnb_heap_alloc(gnb_core->heap, sizeof(node_worker_ctx_t)); memset(node_worker_ctx, 0, sizeof(node_worker_ctx_t)); node_worker_ctx->gnb_core = gnb_core; node_worker_ctx->node_frame_payload = (gnb_payload16_t *)gnb_heap_alloc(gnb_core->heap, gnb_core->conf->payload_block_size); node_worker_ctx->node_frame_payload->type = GNB_PAYLOAD_TYPE_NODE; memory_size = gnb_ring_buffer_fixed_sum_size(GNB_NODE_WORKER_QUEUE_BLOCK_SIZE, gnb_core->conf->node_woker_queue_length); memory = gnb_heap_alloc(gnb_core->heap, memory_size); gnb_worker->ring_buffer_in = gnb_ring_buffer_fixed_init(memory, GNB_NODE_WORKER_QUEUE_BLOCK_SIZE, gnb_core->conf->node_woker_queue_length); gnb_worker->ring_buffer_out = NULL; gnb_worker->ctx = node_worker_ctx; GNB_LOG1(gnb_core->log,GNB_LOG_ID_NODE_WORKER,"%s init finish\n", gnb_worker->name); } static void release(gnb_worker_t *gnb_worker){ node_worker_ctx_t *node_worker_ctx = (node_worker_ctx_t *)gnb_worker->ctx; } static int start(gnb_worker_t *gnb_worker){ node_worker_ctx_t *node_worker_ctx = gnb_worker->ctx; pthread_create(&node_worker_ctx->thread_worker, NULL, thread_worker_func, gnb_worker); pthread_detach(node_worker_ctx->thread_worker); return 0; } static int stop(gnb_worker_t *gnb_worker){ node_worker_ctx_t *node_worker_ctx = gnb_worker->ctx; gnb_core_t *gnb_core = node_worker_ctx->gnb_core; gnb_worker_t *node_worker = gnb_core->node_worker; node_worker->thread_worker_flag = 0; return 0; } static int notify(gnb_worker_t *gnb_worker){ int ret; node_worker_ctx_t *node_worker_ctx = gnb_worker->ctx; ret = pthread_kill(node_worker_ctx->thread_worker,SIGALRM); return 0; } gnb_worker_t gnb_node_worker_mod = { .name = "gnb_node_worker", .init = init, .release = release, .start = start, .stop = stop, .notify = notify, .ctx = NULL }; opengnb-ver1.6.0.a/src/gnb_nodeid.c000077500000000000000000000047661500454252100171430ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 #include #include #include #include #include "gnb_nodeid.h" gnb_uuid_t gnb_str2nodeid(char *nodeidstr){ gnb_uuid_t nodeid; char *endptr; char *p; int is_hex = 0; int i; p = nodeidstr; if ( '$' == *nodeidstr ) { is_hex = 1; p = nodeidstr+1; goto convert_begin; } if ( '0' == *nodeidstr && ( 'x' == *(nodeidstr+1) || 'X' == *(nodeidstr+1) ) ) { is_hex = 1; p = nodeidstr+2; goto convert_begin; } for ( i=0; i<16; i++ ) { if ( *p == '\0' ) { break; } if ( (*p >='A' && *p <='F') || (*p >='a' && *p <='f') ) { is_hex = 1; p = nodeidstr; goto convert_begin; } p++; } convert_begin: if ( is_hex ) { nodeid = strtoull(p, &endptr, 16); } else { nodeid = strtoull(nodeidstr, &endptr, 10); } if ( ERANGE == errno ) { nodeid = 0xFFFFFFFFFFFFFFFF; goto convert_end; } if ( endptr == p ) { nodeid = 0xFFFFFFFFFFFFFFFF; goto convert_end; } convert_end: return nodeid; } char *gnb_nodeid2str(gnb_uuid_t nodeid, char *nodeidstr, int fmt){ #if 0 char buf[GNB_MAX_NODEID_STRING_SIZE]; switch (fmt) { case GNB_NODEIS2STR_FMT_DEC|GNB_NODEIS2STR_FMT_HEX: snprintf(nodeidstr, GNB_MAX_NODEID_STRING_SIZE, "%016"PRIX64"(%"PRIu64")", nodeid, nodeid); break; case GNB_NODEIS2STR_FMT_DEC: snprintf(nodeidstr, GNB_MAX_NODEID_STRING_SIZE, "%"PRIu64"", nodeid); break; case GNB_NODEIS2STR_FMT_HEX: snprintf(nodeidstr, GNB_MAX_NODEID_STRING_SIZE, "%016"PRIX64"", nodeid); break; default: break; } #endif return nodeidstr; } opengnb-ver1.6.0.a/src/gnb_nodeid.h000077500000000000000000000046201500454252100171350ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 . */ #ifndef GNB_NODEID_H #define GNB_NODEID_H #include "gnb_node_type.h" #define GNB_MAX_NODEID_DEC_STRING_SIZE (sizeof("18446744073709551615") - 1) #define GNB_MAX_NODEID_HEX_STRING_SIZE (sizeof("$FFFFFFFFFFFFFFFF") - 1) #define GNB_MAX_NODEID_STRING_SIZE (GNB_MAX_NODEID_DEC_STRING_SIZE+GNB_MAX_NODEID_HEX_STRING_SIZE+3) #define GNB_NODEIS2STR_FMT_DEC (0x1) #define GNB_NODEIS2STR_FMT_HEX (0x1 << 1) gnb_uuid_t gnb_str2nodeid(char *nodeidstr); char *gnb_nodeid2str(gnb_uuid_t nodeid, char *nodeidstr, int fmt); static char gnb_static_nodeid_string_buffer1[GNB_MAX_NODEID_STRING_SIZE]; static char gnb_static_nodeid_string_buffer2[GNB_MAX_NODEID_STRING_SIZE]; static char gnb_static_nodeid_string_buffer3[GNB_MAX_NODEID_STRING_SIZE]; static char gnb_static_nodeid_string_buffer4[GNB_MAX_NODEID_STRING_SIZE]; #define GNB_NODEID_DEC_STR1(nodeid) gnb_nodeid2str(nodeid, gnb_static_nodeid_string_buffer1, GNB_NODEIS2STR_FMT_DEC) #define GNB_NODEID_DEC_STR2(nodeid) gnb_nodeid2str(nodeid, gnb_static_nodeid_string_buffer2, GNB_NODEIS2STR_FMT_DEC) #define GNB_NODEID_DEC_STR3(nodeid) gnb_nodeid2str(nodeid, gnb_static_nodeid_string_buffer3, GNB_NODEIS2STR_FMT_DEC) #define GNB_NODEID_DEC_STR4(nodeid) gnb_nodeid2str(nodeid, gnb_static_nodeid_string_buffer4, GNB_NODEIS2STR_FMT_DEC) #define GNB_NODEID_HEX_STR1(nodeid) gnb_nodeid2str(nodeid, gnb_static_nodeid_string_buffer1, GNB_NODEIS2STR_FMT_HEX) #define GNB_NODEID_HEX_STR2(nodeid) gnb_nodeid2str(nodeid, gnb_static_nodeid_string_buffer2, GNB_NODEIS2STR_FMT_HEX) #define GNB_NODEID_HEX_STR3(nodeid) gnb_nodeid2str(nodeid, gnb_static_nodeid_string_buffer3, GNB_NODEIS2STR_FMT_HEX) #define GNB_NODEID_HEX_STR4(nodeid) gnb_nodeid2str(nodeid, gnb_static_nodeid_string_buffer4, GNB_NODEIS2STR_FMT_HEX) #endif opengnb-ver1.6.0.a/src/gnb_payload16.c000077500000000000000000000221151500454252100174650ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 #include #if defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) #include #endif #ifdef _WIN32 #include #include #endif #include "gnb_payload16.h" gnb_payload16_t* gnb_payload16_init(char type,uint16_t data_size){ gnb_payload16_t *gnb_payload16 = (gnb_payload16_t *)malloc(sizeof(gnb_payload16_t) + sizeof(char)*data_size); memset(gnb_payload16, 0, sizeof(gnb_payload16_t) + sizeof(char)*data_size); gnb_payload16->type = type; gnb_payload16->size = htons(sizeof(gnb_payload16_t) + sizeof(char)*data_size); return gnb_payload16; } gnb_payload16_t* gnb_payload16_create(char type, void *data, uint16_t data_size){ gnb_payload16_t *gnb_payload16 = gnb_payload16_init(type,data_size); memcpy(gnb_payload16->data,data,data_size); return gnb_payload16; } gnb_payload16_t *gnb_payload16_dup(gnb_payload16_t *gnb_payload16_in){ uint16_t size = ntohs(gnb_payload16_in->size); gnb_payload16_t *gnb_payload16 = (gnb_payload16_t *)malloc( size ); memcpy(gnb_payload16, gnb_payload16_in, size); return gnb_payload16; } uint16_t gnb_payload16_set_size(gnb_payload16_t *gnb_payload16, uint16_t new_size){ gnb_payload16->size = htons(new_size); return new_size; } uint16_t gnb_payload16_size(gnb_payload16_t *gnb_payload16){ uint16_t size = ntohs(gnb_payload16->size); return size; } uint16_t gnb_payload16_set_data_len(gnb_payload16_t *gnb_payload16, uint16_t new_len){ gnb_payload16->size = htons(new_len+GNB_PAYLOAD16_HEAD_SIZE); return new_len; } uint16_t gnb_payload16_data_len(gnb_payload16_t *gnb_payload16){ uint16_t size = ntohs(gnb_payload16->size) - GNB_PAYLOAD16_HEAD_SIZE; return size; } void gnb_payload16_free(gnb_payload16_t *gnb_payload16){ free(gnb_payload16); } gnb_payload16_ctx_t* gnb_payload16_ctx_init(uint16_t max_payload_size){ gnb_payload16_ctx_t *gnb_payload16_ctx = (gnb_payload16_ctx_t*)malloc(sizeof(gnb_payload16_ctx_t)); gnb_payload16_ctx->r_len = 0; gnb_payload16_ctx->gnb_payload16 = gnb_payload16_init(0x0, max_payload_size); gnb_payload16_ctx->max_payload_size = max_payload_size; gnb_payload16_ctx->udata = NULL; return gnb_payload16_ctx; } void gnb_payload16_ctx_free(gnb_payload16_ctx_t *gnb_payload16_ctx) { free(gnb_payload16_ctx->gnb_payload16); free(gnb_payload16_ctx); } #define GNB_FRAME_STATUS_HEAD 0 #define GNB_FRAME_STATUS_PART 1 int gnb_payload16_handle(void *data, size_t data_size, gnb_payload16_ctx_t *gnb_payload16_ctx, gnb_payload16_handle_cb_t cb) { uint32_t receive_bytes_offset = 0; ssize_t remain_data_len; int frame_status; uint16_t frame_size; //这里检查到来的数据是否刚好是一个完整的frame,这样对于短小的frame,可以提升处理速度 if ( 0 == gnb_payload16_ctx->r_len && data_size > GNB_PAYLOAD16_HEAD_SIZE ){ frame_size = ntohs(*(uint16_t *)data); if ( 0==frame_size ) { return -1; } if ( (int)frame_size > GNB_MAX_PAYLOAD_SIZE ) { return -2; } if ( frame_size == data_size) { if ( frame_size > gnb_payload16_ctx->max_payload_size ) { return -3; } memcpy( (void *)gnb_payload16_ctx->gnb_payload16, data, frame_size); cb(gnb_payload16_ctx->gnb_payload16, gnb_payload16_ctx->udata); return 0; } } do{ remain_data_len = data_size - receive_bytes_offset; if ( gnb_payload16_ctx->r_len >= 2 ) { frame_status = GNB_FRAME_STATUS_PART; } else { frame_status = GNB_FRAME_STATUS_HEAD; } switch ( frame_status ) { case GNB_FRAME_STATUS_PART: //对于长的frame,这个case出现的概率比较大,所以放前面 frame_size = ntohs(*(uint16_t *)gnb_payload16_ctx->buffer); if ( frame_size > gnb_payload16_ctx->max_payload_size ) { return -4; } if ( remain_data_len >= (frame_size - gnb_payload16_ctx->r_len) ) { //未处理的数据 大于 整个fram的未接收的数据,此时可以得到一个完整的frame memcpy( (void *)gnb_payload16_ctx->gnb_payload16+gnb_payload16_ctx->r_len, data+receive_bytes_offset, (frame_size-gnb_payload16_ctx->r_len) ); receive_bytes_offset += (frame_size-gnb_payload16_ctx->r_len); gnb_payload16_ctx->r_len += (frame_size-gnb_payload16_ctx->r_len); //得到一个完整的 frame 通过 callback函数 传进去处理 cb(gnb_payload16_ctx->gnb_payload16, gnb_payload16_ctx->udata); gnb_payload16_ctx->r_len = 0; //此时由于 gnb_payload16_ctx->r_len == 0,状态会切换到 FE_FRAME_STATUS_HEAD } else { //未处理的数据 小于 整个fram的未接收的数据,此时还不可以得到一个完整的frame //退出处理函数,等下次数据的到来 memcpy( (void *)gnb_payload16_ctx->gnb_payload16+gnb_payload16_ctx->r_len, data+receive_bytes_offset, remain_data_len); gnb_payload16_ctx->r_len += remain_data_len; receive_bytes_offset += remain_data_len; return 0; } break; case GNB_FRAME_STATUS_HEAD: //这里其实不算太复杂,就是要处理一些极端的情况 if ( 0 == gnb_payload16_ctx->r_len ) { //ctx的暂存区为空的情况下,未处理的数据大于 2 byte,此时可以获得frame的首部 if ( remain_data_len >=2 ) { memcpy(gnb_payload16_ctx->buffer, data+receive_bytes_offset, 2); receive_bytes_offset += 2; gnb_payload16_ctx->r_len = 2; } else { //ctx的暂存区为空的情况下,未处理的数据小于 2 byte,此时无法获得frame的首部 //先把 < 2byte 的数据放入ctx的暂存区 memcpy(gnb_payload16_ctx->buffer, data+receive_bytes_offset, remain_data_len); receive_bytes_offset += remain_data_len; gnb_payload16_ctx->r_len = remain_data_len; return 0; } } else if ( gnb_payload16_ctx->r_len > 0 ) { if ( remain_data_len >= (2 - gnb_payload16_ctx->r_len) ) { //ctx的暂存区已经有数据的情况下,ctx的暂存区的数据 合并上 未处理的数据能够取到 2byte 的frame首部 memcpy(gnb_payload16_ctx->buffer+gnb_payload16_ctx->r_len, data+receive_bytes_offset, 2-gnb_payload16_ctx->r_len); receive_bytes_offset += (2-gnb_payload16_ctx->r_len); gnb_payload16_ctx->r_len += (2-gnb_payload16_ctx->r_len); } else { //ctx的暂存区已经有数据的情况下,ctx的暂存区的数据 合并上 未处理的数据还是不足取到 2byte 的frame首部 //退出处理函数,等下次数据的到来 memcpy(gnb_payload16_ctx->buffer+gnb_payload16_ctx->r_len, data+receive_bytes_offset, remain_data_len); gnb_payload16_ctx->r_len += remain_data_len; return 0; } } if ( 2 == gnb_payload16_ctx->r_len ) { //已经取到2byte 的frame首部 frame_size = ntohs(*(uint16_t *)gnb_payload16_ctx->buffer); //检查frame首部(frame长度)是否合法 if ( 0 == frame_size ) { return -1; } if ( (int)frame_size > GNB_MAX_PAYLOAD_SIZE ) { return -2; } //根据 frame_size 创建 payload 结构体 if ( frame_size > gnb_payload16_ctx->max_payload_size ) { return -3; } memcpy( (void *)gnb_payload16_ctx->gnb_payload16, gnb_payload16_ctx->buffer, 2); //此时,由于gnb_payload16_ctx->r_len == 2,因此在循环的时候,状态会切换到 FE_FRAME_STATUS_PART } break; default: //Error!!! break; } }while( (data_size - receive_bytes_offset) > 0 ); return 0; } opengnb-ver1.6.0.a/src/gnb_payload16.h000077500000000000000000000050271500454252100174750ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 . */ #ifndef GNB_PAYLOAD16_H #define GNB_PAYLOAD16_H #include #include #include #include #include #pragma pack(push, 1) typedef struct _gnb_payload16_t{ uint16_t size; unsigned char type; unsigned char sub_type; unsigned char data[0]; } __attribute__ ((packed)) gnb_payload16_t; #pragma pack(pop) #define GNB_PAYLOAD16_HEAD_SIZE 4 #define GNB_MAX_PAYLOAD_SIZE 65535 gnb_payload16_t* gnb_payload16_init(char type,uint16_t data_size); gnb_payload16_t* gnb_payload16_create(char type, void *data, uint16_t data_size); gnb_payload16_t *gnb_payload16_dup(gnb_payload16_t *gnb_payload16_in); void gnb_payload16_free(gnb_payload16_t *gnb_payload16); uint16_t gnb_payload16_set_size(gnb_payload16_t *gnb_payload16, uint16_t new_size); uint16_t gnb_payload16_size(gnb_payload16_t *gnb_payload16); uint16_t gnb_payload16_set_data_len(gnb_payload16_t *gnb_payload16, uint16_t new_len); uint16_t gnb_payload16_data_len(gnb_payload16_t *gnb_payload16); typedef struct _gnb_payload16_ctx_t{ //当前 当前payload(frame) 已收到的字节数 //r_len足2字节时,接收的数据存 gnb_payload //r_len 不足2字节时,接收的数据存 buffer int r_len; unsigned char buffer[2]; //传入payload gnb_payload16_t *gnb_payload16; //传入的 payload 内存块大小 uint32_t max_payload_size; void *udata; }gnb_payload16_ctx_t; gnb_payload16_ctx_t* gnb_payload16_ctx_init(uint16_t max_payload_size); void gnb_payload16_ctx_free(gnb_payload16_ctx_t *gnb_payload16_ctx); typedef int (*gnb_payload16_handle_cb_t)(gnb_payload16_t *gnb_payload16, void *ctx); int gnb_payload16_handle(void *data, size_t data_size, gnb_payload16_ctx_t *gnb_payload16_ctx, gnb_payload16_handle_cb_t cb); #define GNB_PAYLOAD16_FRAME_SIZE(payload) gnb_payload16_size(payload) #define GNB_PAYLOAD16_DATA_SIZE(payload) gnb_payload16_data_len(payload) #endif opengnb-ver1.6.0.a/src/gnb_pf.c000077500000000000000000000660351500454252100163030ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 #include "gnb.h" #include "gnb_node.h" #include "gnb_hash32.h" #include "gnb_pf.h" #include "gnb_payload16.h" #include "gnb_unified_forwarding.h" #include "gnb_binary.h" void gnb_send_ur0_frame(gnb_core_t *gnb_core, gnb_node_t *dst_node, gnb_payload16_t *payload); gnb_node_t* gnb_query_route4(gnb_core_t *gnb_core, uint32_t dst_ip_int){ char ip_string[INET_ADDRSTRLEN]; inet_ntop(AF_INET, &dst_ip_int, ip_string, INET_ADDRSTRLEN); gnb_node_t *node=NULL; uint32_t dsp_ip_key = dst_ip_int; node = GNB_HASH32_UINT32_GET_PTR(gnb_core->ipv4_node_map, dsp_ip_key); if ( node ) { goto finish; } dsp_ip_key = dst_ip_int & htonl(IN_CLASSC_NET); node = GNB_HASH32_UINT32_GET_PTR(gnb_core->subnetc_node_map, dsp_ip_key); if ( node ) { goto finish; } dsp_ip_key = dst_ip_int & htonl(IN_CLASSB_NET); node = GNB_HASH32_UINT32_GET_PTR(gnb_core->subnetb_node_map, dsp_ip_key); if ( node ) { goto finish; } dsp_ip_key = dst_ip_int & htonl(IN_CLASSA_NET); node = GNB_HASH32_UINT32_GET_PTR(gnb_core->subneta_node_map, dsp_ip_key); if ( node ) { goto finish; } finish: return node; } #define GNB_PF_TUN_FRAME_INIT 0 #define GNB_PF_TUN_FRAME_ERROR 1 #define GNB_PF_TUN_FRAME_DROP 2 #define GNB_PF_TUN_FRAME_NEXT 3 #define GNB_PF_TUN_FRAME_FINISH 4 #define GNB_PF_TUN_ROUTE_INIT 5 #define GNB_PF_TUN_ROUTE_ERROR 6 #define GNB_PF_TUN_ROUTE_DROP 7 #define GNB_PF_TUN_ROUTE_NOROUTE 8 #define GNB_PF_TUN_ROUTE_NEXT 9 #define GNB_PF_TUN_ROUTE_FINISH 10 #define GNB_PF_TUN_FORWARD_INIT 11 #define GNB_PF_TUN_FORWARD_ERROR 12 #define GNB_PF_TUN_FORWARD_NEXT 13 #define GNB_PF_TUN_FORWARD_FINISH 14 #define GNB_PF_INET_FRAME_INIT 15 #define GNB_PF_INET_FRAME_ERROR 16 #define GNB_PF_INET_FRAME_NOROUTE 17 #define GNB_PF_INET_FRAME_DROP 18 #define GNB_PF_INET_FRAME_NEXT 19 #define GNB_PF_INET_FRAME_FINISH 20 #define GNB_PF_INET_ROUTE_INIT 21 #define GNB_PF_INET_ROUTE_ERROR 22 #define GNB_PF_INET_ROUTE_DROP 23 #define GNB_PF_INET_ROUTE_NOROUTE 24 #define GNB_PF_INET_ROUTE_NEXT 25 #define GNB_PF_INET_ROUTE_FINISH 26 #define GNB_PF_INET_FORWARD_INIT 27 #define GNB_PF_INET_FORWARD_ERROR 28 #define GNB_PF_INET_FORWARD_DROP 29 #define GNB_PF_INET_FORWARD_NEXT 30 #define GNB_PF_INET_FORWARD_FINISH 31 #define GNB_PF_INET_FORWARD_TO_TUN 32 #define GNB_PF_INET_FORWARD_TO_INET 33 static char* gnb_pf_status_strings[34]; void gnb_pf_status_strings_init() { gnb_pf_status_strings[GNB_PF_TUN_FRAME_INIT] = "TUN_FRAME_INIT"; gnb_pf_status_strings[GNB_PF_TUN_FRAME_ERROR] = "TUN_FRAME_ERROR"; gnb_pf_status_strings[GNB_PF_TUN_FRAME_DROP] = "TUN_FRAME_DROP"; gnb_pf_status_strings[GNB_PF_TUN_FRAME_NEXT] = "TUN_FRAME_NEXT"; gnb_pf_status_strings[GNB_PF_TUN_FRAME_FINISH] = "TUN_FRAME_FINISH"; gnb_pf_status_strings[GNB_PF_TUN_ROUTE_INIT] = "TUN_ROUTE_INIT"; gnb_pf_status_strings[GNB_PF_TUN_ROUTE_ERROR] = "TUN_ROUTE_ERROR"; gnb_pf_status_strings[GNB_PF_TUN_ROUTE_DROP] = "TUN_ROUTE_DROP"; gnb_pf_status_strings[GNB_PF_TUN_ROUTE_NOROUTE] = "TUN_ROUTE_NOROUTE"; gnb_pf_status_strings[GNB_PF_TUN_ROUTE_NEXT] = "TUN_ROUTE_NEXT"; gnb_pf_status_strings[GNB_PF_TUN_ROUTE_FINISH] = "TUN_ROUTE_FINISH"; gnb_pf_status_strings[GNB_PF_TUN_FORWARD_INIT] = "TUN_FORWARD_INIT"; gnb_pf_status_strings[GNB_PF_TUN_FORWARD_ERROR] = "TUN_FORWARD_ERROR"; gnb_pf_status_strings[GNB_PF_TUN_FORWARD_NEXT] = "TUN_FORWARD_NEXT"; gnb_pf_status_strings[GNB_PF_TUN_FORWARD_FINISH] = "TUN_FORWARD_FINISH"; gnb_pf_status_strings[GNB_PF_INET_FRAME_INIT] = "INET_FRAME_INIT"; gnb_pf_status_strings[GNB_PF_INET_FRAME_ERROR] = "INET_FRAME_ERROR"; gnb_pf_status_strings[GNB_PF_INET_FRAME_NOROUTE] = "INET_FRAME_NOROUTE"; gnb_pf_status_strings[GNB_PF_INET_FRAME_DROP] = "INET_FRAME_DROP"; gnb_pf_status_strings[GNB_PF_INET_FRAME_NEXT] = "INET_FRAME_NEXT"; gnb_pf_status_strings[GNB_PF_INET_FRAME_FINISH] = "INET_FRAME_FINISH"; gnb_pf_status_strings[GNB_PF_INET_ROUTE_INIT] = "INET_ROUTE_INIT"; gnb_pf_status_strings[GNB_PF_INET_ROUTE_ERROR] = "INET_ROUTE_ERROR"; gnb_pf_status_strings[GNB_PF_INET_ROUTE_DROP] = "INET_ROUTE_DROP"; gnb_pf_status_strings[GNB_PF_INET_ROUTE_NOROUTE] = "INET_ROUTE_NOROUTE"; gnb_pf_status_strings[GNB_PF_INET_ROUTE_NEXT] = "INET_ROUTE_NEXT"; gnb_pf_status_strings[GNB_PF_INET_ROUTE_FINISH] = "INET_ROUTE_FINISH"; gnb_pf_status_strings[GNB_PF_INET_FORWARD_INIT] = "INET_FORWARD_INIT"; gnb_pf_status_strings[GNB_PF_INET_FORWARD_ERROR] = "INET_FORWARD_ERROR"; gnb_pf_status_strings[GNB_PF_INET_FORWARD_DROP] = "INET_FORWARD_DROP"; gnb_pf_status_strings[GNB_PF_INET_FORWARD_NEXT] = "INET_FORWARD_NEXT"; gnb_pf_status_strings[GNB_PF_INET_FORWARD_TO_TUN] = "INET_FORWARD_TO_TUN"; gnb_pf_status_strings[GNB_PF_INET_FORWARD_TO_INET] = "INET_FORWARD_TO_INET"; } static gnb_pf_t* find_pf_in_array(gnb_pf_array_t *pf_array, const char *pf_name) { int i; for ( i=0; inum; i++ ) { if ( NULL==pf_array->pf[i] ) { break; } if ( 0 == strncmp(pf_array->pf[i]->name, pf_name, 128) ) { return pf_array->pf[i]; } } return NULL; } static gnb_pf_array_t* gnb_pf_array_init(gnb_heap_t *heap, int size){ gnb_pf_array_t *pf_array; pf_array = (gnb_pf_array_t *)gnb_heap_alloc(heap, sizeof(gnb_pf_array_t) + sizeof(gnb_pf_t)*size); pf_array->size = size; pf_array->num = 0; return pf_array; } gnb_pf_core_t* gnb_pf_core_init(gnb_heap_t *heap, int size){ gnb_pf_core_t *pf_core; pf_core = gnb_heap_alloc(heap, sizeof(gnb_pf_core_t)); pf_core->pf_install_array = gnb_pf_array_init(heap, size); pf_core->pf_tun_frame_array = gnb_pf_array_init(heap, size); pf_core->pf_tun_route_array = gnb_pf_array_init(heap, size); pf_core->pf_tun_fwd_array = gnb_pf_array_init(heap, size); pf_core->pf_inet_frame_array = gnb_pf_array_init(heap, size); pf_core->pf_inet_route_array = gnb_pf_array_init(heap, size); pf_core->pf_inet_fwd_array = gnb_pf_array_init(heap, size); return pf_core; } void gnb_pf_core_release(gnb_core_t *gnb_core, gnb_pf_core_t *pf_core) { int i; for ( i=0; ipf_install_array->num; i++ ) { if ( NULL==pf_core->pf_install_array->pf[i]->pf_release ) { continue; } pf_core->pf_install_array->pf[i]->pf_release(gnb_core, pf_core->pf_install_array->pf[i]); } } void gnb_pf_core_conf(gnb_core_t *gnb_core, gnb_pf_core_t *pf_core){ gnb_pf_array_t *pf_array; pf_array = pf_core->pf_install_array; gnb_pf_t *pf_dump; gnb_pf_t *pf_route; gnb_pf_t *pf_zip; gnb_pf_t *pf_crypto; pf_dump = find_pf_in_array(pf_array, "gnb_pf_dump"); pf_route = find_pf_in_array(pf_array, gnb_core->conf->pf_route); pf_zip = find_pf_in_array(pf_array, "gnb_pf_zip"); pf_crypto = find_pf_in_array(pf_array, "gnb_pf_crypto_xor"); if ( NULL == pf_crypto ) { pf_crypto = find_pf_in_array(pf_array, "gnb_pf_crypto_arc4"); } int idx; //pf_tun //pf_tun_frame gnb_pf_dump -> gnb_pf_route idx = 0; if ( NULL != pf_dump ) { pf_core->pf_tun_frame_array->pf[idx++] = pf_dump; } pf_core->pf_tun_frame_array->pf[idx++] = pf_route; pf_core->pf_tun_frame_array->num = idx; //pf_tun_route gnb_pf_route[+] -> gnb_pf_zip -> gnb_pf_crypto(p2p) idx = 0; pf_core->pf_tun_route_array->pf[idx++] = pf_route; if ( NULL != pf_zip) { pf_core->pf_tun_route_array->pf[idx++] = pf_zip; } if ( NULL != pf_crypto ) { pf_core->pf_tun_route_array->pf[idx++] = pf_crypto; //p2p } pf_core->pf_tun_route_array->num = idx; //pf_tun_fwd gnb_pf_crypto(relay) idx = 0; if ( NULL != pf_crypto ) { pf_core->pf_tun_fwd_array->pf[idx++] = pf_crypto; //relay } pf_core->pf_tun_fwd_array->num = idx; //pf_inet //pf_inet_frame gnb_pf_crypto(relay) -> gnb_pf_route idx = 0; if ( NULL != pf_crypto ) { pf_core->pf_inet_frame_array->pf[idx++] = pf_crypto; //relay } pf_core->pf_inet_frame_array->pf[idx++] = pf_route; pf_core->pf_inet_frame_array->num = idx; //pf_inet_route gnb_pf_route -> gnb_pf_crypto(p2p) -> gnb_pf_zip idx = 0; pf_core->pf_inet_route_array->pf[idx++] = pf_route; if ( NULL != pf_crypto ) { pf_core->pf_inet_route_array->pf[idx++] = pf_crypto; //p2p } if ( NULL != pf_zip ) { pf_core->pf_inet_route_array->pf[idx++] = pf_zip; } pf_core->pf_inet_route_array->num = idx; //pf_inet_fwd gnb_pf_dump -> gnb_pf_route -> gnb_pf_crypto(relay) idx = 0; if ( NULL != pf_dump ) { pf_core->pf_inet_fwd_array->pf[idx++] = pf_dump; } pf_core->pf_inet_fwd_array->pf[idx++] = pf_route; if ( NULL != pf_crypto ) { pf_core->pf_inet_fwd_array->pf[idx++] = pf_crypto; //relay } pf_core->pf_inet_fwd_array->num = idx; return; } int gnb_pf_install(gnb_pf_array_t *pf_array, gnb_pf_t *pf){ if ( pf_array->num >= pf_array->size ) { return -1; } pf_array->pf[pf_array->num] = pf; pf_array->num++; return 0; } void gnb_pf_init(gnb_core_t *gnb_core, gnb_pf_array_t *pf_array){ int i; for ( i=0; inum; i++ ) { if ( NULL==pf_array->pf[i]->pf_init ) { continue; } pf_array->pf[i]->pf_init(gnb_core,pf_array->pf[i]); } } void gnb_pf_conf(gnb_core_t *gnb_core, gnb_pf_array_t *pf_array){ int i; for ( i=0; inum; i++ ) { if ( NULL==pf_array->pf[i]->pf_conf ) { continue; } pf_array->pf[i]->pf_conf(gnb_core,pf_array->pf[i]); } } /* 把输入的 payload 加上offset,这样pf模块处理的时候,就可以在offset之前填充pf的头部,减少一次通过 memcpy 重组payload */ void gnb_pf_tun(gnb_core_t *gnb_core, gnb_pf_core_t *pf_core, gnb_payload16_t *payload){ int i; int ret; gnb_pf_ctx_t pf_ctx_st; gnb_pf_array_t *pf_tun_frame_array = pf_core->pf_tun_frame_array; gnb_pf_array_t *pf_tun_route_array = pf_core->pf_tun_route_array; gnb_pf_array_t *pf_tun_fwd_array = pf_core->pf_tun_fwd_array; memset(&pf_ctx_st,0,sizeof(gnb_pf_ctx_t)); pf_ctx_st.pf_fwd = GNB_PF_FWD_INIT; pf_ctx_st.fwd_payload = payload; pf_ctx_st.fwd_payload->type = GNB_PAYLOAD_TYPE_IPFRAME; pf_ctx_st.fwd_payload->sub_type = GNB_PAYLOAD_SUB_TYPE_IPFRAME_INIT; int pf_tun_frame_status = GNB_PF_TUN_FRAME_INIT; int pf_tun_route_status = GNB_PF_TUN_ROUTE_INIT; int pf_tun_forward_status = GNB_PF_TUN_FORWARD_INIT; gnb_uuid_t fwd_uuid64 = 0; gnb_core->select_fwd_node = gnb_select_forward_node(gnb_core); pf_ctx_st.pf_status = GNB_PF_TUN_FRAME_INIT; if ( 1 == gnb_core->conf->if_dump ) { GNB_LOG3(gnb_core->log, GNB_LOG_ID_PF, "----- GNB PF TUN BEGIN -----\n"); } for ( i=0; inum; i++ ) { if ( NULL==pf_tun_frame_array->pf[i]->pf_tun_frame ) { continue; } pf_ctx_st.pf_status = pf_tun_frame_array->pf[i]->pf_tun_frame(gnb_core, pf_tun_frame_array->pf[i], &pf_ctx_st); switch (pf_ctx_st.pf_status) { case GNB_PF_ERROR: pf_tun_frame_status = GNB_PF_TUN_FRAME_ERROR; break; case GNB_PF_DROP: pf_tun_frame_status = GNB_PF_TUN_FRAME_DROP; break; case GNB_PF_NEXT: pf_tun_frame_status = GNB_PF_TUN_FRAME_NEXT; break; case GNB_PF_FINISH: pf_tun_frame_status = GNB_PF_TUN_FRAME_FINISH; break; default: break; } GNB_LOG3(gnb_core->log, GNB_LOG_ID_PF, ">>> tun payload pf_tun_frame:[%s] => %s\n", pf_tun_frame_array->pf[i]->name, gnb_pf_status_strings[pf_tun_frame_status]); if ( GNB_PF_FINISH == pf_ctx_st.pf_status ) { break; } if ( GNB_PF_ERROR == pf_ctx_st.pf_status || GNB_PF_DROP == pf_ctx_st.pf_status ) { goto pf_tun_finish; } } pf_ctx_st.pf_status = GNB_PF_TUN_ROUTE_INIT; for ( i=0; inum; i++ ) { if ( NULL == pf_tun_route_array->pf[i]->pf_tun_route ) { continue; } pf_ctx_st.pf_status = pf_tun_route_array->pf[i]->pf_tun_route(gnb_core, pf_tun_route_array->pf[i], &pf_ctx_st); switch (pf_ctx_st.pf_status) { case GNB_PF_ERROR: pf_tun_route_status = GNB_PF_TUN_ROUTE_ERROR; break; case GNB_PF_NOROUTE: pf_tun_route_status = GNB_PF_TUN_ROUTE_NOROUTE; break; case GNB_PF_DROP: pf_tun_route_status = GNB_PF_TUN_ROUTE_DROP; break; case GNB_PF_NEXT: pf_tun_route_status = GNB_PF_TUN_ROUTE_NEXT; break; default: break; } GNB_LOG3(gnb_core->log, GNB_LOG_ID_PF, ">>> tun payload pf_tun_route:[%s] %s\n", pf_tun_route_array->pf[i]->name, gnb_pf_status_strings[pf_tun_route_status]); if ( GNB_PF_ERROR == pf_ctx_st.pf_status ) { goto pf_tun_finish; } } /* * 一般的,forwarding 的优先级是 relay_forwarding > unified_forwarding > direct_forwarding > std_forwarding * 以下条件跳转是确保 relay_forwarding > unified_forwarding * */ if ( NULL != pf_ctx_st.fwd_node && 1 == pf_ctx_st.relay_forwarding ) { goto pf_tun_fwd; } if ( GNB_UNIFIED_FORWARDING_OFF == gnb_core->conf->unified_forwarding ) { goto skip_unified_forwarding; } if ( GNB_UNIFIED_FORWARDING_FORCE == gnb_core->conf->unified_forwarding ) { GNB_LOG3(gnb_core->log, GNB_LOG_ID_PF, "Unified Forwarding Force src=%llu dst=%llu\n", pf_ctx_st.src_uuid64, pf_ctx_st.dst_uuid64); ret = gnb_unified_forwarding_tun(gnb_core, &pf_ctx_st); if ( ret > 0 ) { pf_ctx_st.unified_forwarding = 1; } else { pf_ctx_st.unified_forwarding = 0; } goto pf_tun_finish; } if ( NULL == pf_ctx_st.fwd_node && GNB_UNIFIED_FORWARDING_AUTO == gnb_core->conf->unified_forwarding ) { GNB_LOG3(gnb_core->log, GNB_LOG_ID_PF, "Unified Forwarding Auto src=%llu dst=%llu\n", pf_ctx_st.src_uuid64, pf_ctx_st.dst_uuid64); ret = gnb_unified_forwarding_tun(gnb_core, &pf_ctx_st); if ( ret > 0 ) { pf_ctx_st.unified_forwarding = 1; } else { pf_ctx_st.unified_forwarding = 0; } goto pf_tun_finish; } if ( GNB_UNIFIED_FORWARDING_SUPER == gnb_core->conf->unified_forwarding || GNB_UNIFIED_FORWARDING_HYPER == gnb_core->conf->unified_forwarding ) { GNB_LOG3(gnb_core->log, GNB_LOG_ID_PF, "Unified Forwarding Multi-Path src=%llu dst=%llu\n", pf_ctx_st.src_uuid64, pf_ctx_st.dst_uuid64); ret = gnb_unified_forwarding_with_multi_path_tun(gnb_core, &pf_ctx_st); if ( 0 == ret ) { pf_ctx_st.unified_forwarding = 1; } else { pf_ctx_st.unified_forwarding = 0; } goto pf_tun_finish; } skip_unified_forwarding: if ( NULL == pf_ctx_st.fwd_node ) { goto pf_tun_finish; } pf_tun_fwd: pf_ctx_st.pf_status = GNB_PF_TUN_FORWARD_INIT; for ( i=0; i < pf_tun_fwd_array->num; i++ ) { if ( NULL==pf_tun_fwd_array->pf[i]->pf_tun_fwd ) { continue; } pf_ctx_st.pf_status = pf_tun_fwd_array->pf[i]->pf_tun_fwd(gnb_core, pf_tun_fwd_array->pf[i], &pf_ctx_st); switch (pf_ctx_st.pf_status) { case GNB_PF_ERROR: pf_tun_forward_status = GNB_PF_TUN_FORWARD_ERROR; break; case GNB_PF_NEXT: pf_tun_forward_status = GNB_PF_TUN_FORWARD_NEXT; break; case GNB_PF_FINISH: pf_tun_forward_status = GNB_PF_TUN_FORWARD_FINISH; break; default: break; } GNB_LOG3(gnb_core->log, GNB_LOG_ID_PF, ">>> tun payload pf_tun_fwd:[%s] %s\n", pf_tun_fwd_array->pf[i]->name, gnb_pf_status_strings[pf_tun_forward_status]); if ( GNB_PF_ERROR == pf_ctx_st.pf_status ) { goto pf_tun_finish; } if ( GNB_PF_FINISH == pf_ctx_st.pf_status ) { break; } } gnb_p2p_forward_payload_to_node(gnb_core, pf_ctx_st.fwd_node, pf_ctx_st.fwd_payload); if ( 1 == gnb_core->conf->if_dump ) { GNB_LOG3(gnb_core->log, GNB_LOG_ID_PF, "payload frome TUN to INET node=%llu [%s]\n", pf_ctx_st.fwd_node->uuid64, GNB_HEX2_BYTE256((void *)pf_ctx_st.fwd_payload) ); } pf_ctx_st.fwd_node->in_bytes += pf_ctx_st.ip_frame_size; gnb_core->local_node->out_bytes += pf_ctx_st.ip_frame_size; if ( pf_ctx_st.dst_uuid64 == pf_ctx_st.fwd_node->uuid64 ) { GNB_LOG3(gnb_core->log, GNB_LOG_ID_PF, ">>> tun payload forward to inet src=%llu dst=%llu >>>\n", pf_ctx_st.src_uuid64, pf_ctx_st.fwd_node->uuid64); } else { GNB_LOG3(gnb_core->log, GNB_LOG_ID_PF, "*>> tun payload forward to inet src=%llu dst=%llu fwd=%llu *>>\n", pf_ctx_st.src_uuid64, pf_ctx_st.dst_uuid64, pf_ctx_st.fwd_node->uuid64); } pf_tun_finish: if ( 0 == pf_ctx_st.unified_forwarding && NULL != pf_ctx_st.dst_node && NULL == pf_ctx_st.fwd_node && 1 == pf_ctx_st.universal_udp4_relay ) { gnb_send_ur0_frame(gnb_core, pf_ctx_st.dst_node, pf_ctx_st.fwd_payload); GNB_LOG3(gnb_core->log, GNB_LOG_ID_PF, "tun try to universal relay src=%llu dst=%llu\n", pf_ctx_st.src_uuid64, pf_ctx_st.dst_uuid64); } if_dump: if ( 1 == gnb_core->conf->if_dump ) { fwd_uuid64 = NULL != pf_ctx_st.fwd_node ? pf_ctx_st.fwd_node->uuid64:0; GNB_LOG3(gnb_core->log, GNB_LOG_ID_PF, "tun src=%llu dst=%llu fwd=%llu [%s] [%s] relay=%d,unified=%d,direct=%d,forward=%d ip_frame_size=%u\n", pf_ctx_st.src_uuid64, pf_ctx_st.dst_uuid64, fwd_uuid64, gnb_pf_status_strings[pf_tun_frame_status], gnb_pf_status_strings[pf_tun_route_status], pf_ctx_st.relay_forwarding, pf_ctx_st.unified_forwarding, pf_ctx_st.direct_forwarding, pf_ctx_st.std_forwarding, pf_ctx_st.ip_frame_size); } if ( 1 == gnb_core->conf->if_dump ) { GNB_LOG3(gnb_core->log, GNB_LOG_ID_PF, "----- GNB PF TUN END -----\n"); } finish: return; } void gnb_pf_inet(gnb_core_t *gnb_core, gnb_pf_core_t *pf_core, gnb_payload16_t *payload, gnb_sockaddress_t *source_node_addr){ gnb_pf_ctx_t pf_ctx_st; gnb_pf_array_t *pf_inet_frame_array = pf_core->pf_inet_frame_array; gnb_pf_array_t *pf_inet_route_array = pf_core->pf_inet_route_array; gnb_pf_array_t *pf_inet_fwd_array = pf_core->pf_inet_fwd_array; memset(&pf_ctx_st,0,sizeof(gnb_pf_ctx_t)); pf_ctx_st.pf_fwd = GNB_PF_FWD_INIT; pf_ctx_st.fwd_payload = payload; pf_ctx_st.source_node_addr = source_node_addr; int i; int pf_inet_frame_status = GNB_PF_INET_FRAME_INIT; int pf_inet_route_status = GNB_PF_INET_ROUTE_INIT; int pf_inet_forwad_status = GNB_PF_INET_FORWARD_INIT; int ret; gnb_uuid_t fwd_uuid64 = 0; gnb_core->select_fwd_node = gnb_select_forward_node(gnb_core); if ( 1 == gnb_core->conf->if_dump ) { GNB_LOG3(gnb_core->log, GNB_LOG_ID_PF, "----- GNB PF INET BEGIN -----\n"); } if ( GNB_PAYLOAD_SUB_TYPE_IPFRAME_UNIFIED == payload->sub_type ) { //如果 ip分组 不是转发到本节点,就转发到目的节点 ret = gnb_unified_forwarding_inet(gnb_core, payload); if ( UNIFIED_FORWARDING_TO_TUN != ret ) { goto pf_inet_finish; } } if ( GNB_PAYLOAD_SUB_TYPE_IPFRAME_UNIFIED_MULTI_PATH == payload->sub_type ) { //如果 ip分组 不是转发到本节点,就转发到目的节点 ret = gnb_unified_forwarding_multi_path_inet(gnb_core, payload); if ( UNIFIED_FORWARDING_TO_TUN != ret ) { goto pf_inet_finish; } } for ( i=0; inum; i++ ) { if ( NULL == pf_inet_frame_array->pf[i]->pf_inet_frame ) { continue; } pf_ctx_st.pf_status = pf_inet_frame_array->pf[i]->pf_inet_frame(gnb_core, pf_inet_frame_array->pf[i], &pf_ctx_st); switch (pf_ctx_st.pf_status) { case GNB_PF_NOROUTE: pf_inet_frame_status = GNB_PF_INET_FRAME_NOROUTE; break; case GNB_PF_ERROR: pf_inet_frame_status = GNB_PF_INET_FRAME_ERROR; break; case GNB_PF_DROP: pf_inet_frame_status = GNB_PF_INET_FRAME_DROP; break; case GNB_PF_FINISH: pf_inet_frame_status = GNB_PF_INET_FRAME_FINISH; break; default: break; } GNB_LOG3(gnb_core->log, GNB_LOG_ID_PF, "<<< inet payload pf_inet_frame:[%s] %s\n", pf_inet_frame_array->pf[i]->name, gnb_pf_status_strings[pf_inet_frame_status]); if ( GNB_PF_ERROR == pf_ctx_st.pf_status || GNB_PF_DROP == pf_ctx_st.pf_status ) { goto pf_inet_finish; } if ( GNB_PF_FINISH == pf_ctx_st.pf_status ) { break; } } for ( i=0; inum; i++ ) { if ( NULL == pf_inet_route_array->pf[i]->pf_inet_route ) { continue; } pf_ctx_st.pf_status = pf_inet_route_array->pf[i]->pf_inet_route(gnb_core, pf_inet_route_array->pf[i], &pf_ctx_st); switch (pf_ctx_st.pf_status) { case GNB_PF_ERROR: pf_inet_route_status = GNB_PF_INET_ROUTE_ERROR; break; case GNB_PF_DROP: pf_inet_route_status = GNB_PF_INET_ROUTE_DROP; break; case GNB_PF_NOROUTE: pf_inet_route_status = GNB_PF_INET_ROUTE_NOROUTE; break; case GNB_PF_NEXT: pf_inet_route_status = GNB_PF_INET_ROUTE_NEXT; break; case GNB_PF_FINISH: pf_inet_route_status = GNB_PF_INET_ROUTE_FINISH; break; default: break; } GNB_LOG3(gnb_core->log, GNB_LOG_ID_PF, "<<< inet payload pf_inet_route:[%s] %s\n", pf_inet_route_array->pf[i]->name, gnb_pf_status_strings[pf_inet_route_status]); if ( GNB_PF_ERROR == pf_ctx_st.pf_status || GNB_PF_DROP == pf_ctx_st.pf_status || GNB_PF_NOROUTE == pf_ctx_st.pf_status ) { goto pf_inet_finish; } if ( GNB_PF_FINISH == pf_ctx_st.pf_status ) { break; } } for ( i=0; inum; i++ ) { if ( NULL == pf_inet_fwd_array->pf[i]->pf_inet_fwd ) { continue; } pf_ctx_st.pf_status = pf_inet_fwd_array->pf[i]->pf_inet_fwd(gnb_core, pf_inet_fwd_array->pf[i], &pf_ctx_st); switch (pf_ctx_st.pf_status) { case GNB_PF_ERROR: pf_inet_forwad_status = GNB_PF_INET_FORWARD_ERROR; break; case GNB_PF_DROP: pf_inet_forwad_status = GNB_PF_INET_FORWARD_DROP; break; case GNB_PF_NEXT: pf_inet_forwad_status = GNB_PF_INET_FORWARD_NEXT; break; case GNB_PF_FINISH: pf_inet_forwad_status = GNB_PF_INET_FORWARD_FINISH; break; default: break; } GNB_LOG3(gnb_core->log, GNB_LOG_ID_PF, "<<< inet payload pf_inet_fwd:[%s] %s\n", pf_inet_fwd_array->pf[i]->name, gnb_pf_status_strings[pf_inet_forwad_status]); if ( GNB_PF_ERROR == pf_ctx_st.pf_status || GNB_PF_DROP == pf_ctx_st.pf_status ) { goto pf_inet_finish; } if ( GNB_PF_FINISH == pf_ctx_st.pf_status ) { break; } } fwd_uuid64 = NULL!=pf_ctx_st.fwd_node ? pf_ctx_st.fwd_node->uuid64:0; if ( NULL == pf_ctx_st.src_node ) { goto pf_inet_finish; } if ( gnb_core->conf->activate_tun && GNB_PF_FWD_TUN == pf_ctx_st.pf_fwd ) { gnb_core->drv->write_tun(gnb_core, pf_ctx_st.ip_frame, pf_ctx_st.ip_frame_size); if ( 1 == gnb_core->conf->if_dump ) { GNB_LOG3(gnb_core->log, GNB_LOG_ID_PF, "payload frome INET to TUN src node=%llu [%s]\n", pf_ctx_st.src_node->uuid64, GNB_HEX2_BYTE256((void *)pf_ctx_st.fwd_payload) ); } fwd_uuid64 = pf_ctx_st.dst_uuid64; pf_inet_forwad_status = GNB_PF_INET_FORWARD_TO_TUN; gnb_core->local_node->in_bytes += pf_ctx_st.ip_frame_size; pf_ctx_st.src_node->out_bytes += pf_ctx_st.ip_frame_size; GNB_LOG3(gnb_core->log, GNB_LOG_ID_PF, "<<< inet payload forward to tun src=%llu dst=%llu <<<\n", pf_ctx_st.src_uuid64, pf_ctx_st.dst_uuid64); goto pf_inet_finish; } if ( GNB_PF_FWD_INET == pf_ctx_st.pf_fwd && NULL != pf_ctx_st.fwd_node && NULL != pf_ctx_st.fwd_payload ) { gnb_p2p_forward_payload_to_node(gnb_core, pf_ctx_st.fwd_node, pf_ctx_st.fwd_payload); if ( 1 == gnb_core->conf->if_dump ) { GNB_LOG3(gnb_core->log, GNB_LOG_ID_PF, "payload frome INET to INET dst node=%llu [%s]\n", pf_ctx_st.fwd_node->uuid64, GNB_HEX2_BYTE256((void *)pf_ctx_st.fwd_payload) ); } pf_inet_forwad_status = GNB_PF_INET_FORWARD_TO_INET; gnb_core->local_node->out_bytes += pf_ctx_st.ip_frame_size; pf_ctx_st.fwd_node->in_bytes += pf_ctx_st.ip_frame_size; GNB_LOG3(gnb_core->log, GNB_LOG_ID_PF, "<*< inet payload forward to inet src=%llu dst=%llu fwd=%llu >*>\n", pf_ctx_st.src_uuid64, pf_ctx_st.dst_uuid64, fwd_uuid64); } pf_inet_finish: if ( 1 == gnb_core->conf->if_dump ) { GNB_LOG3(gnb_core->log, GNB_LOG_ID_PF, "inet src=%llu dst=%llu fwd=%llu [%s] [%s] [%s] ip_frame_size=%u\n", pf_ctx_st.src_uuid64, pf_ctx_st.dst_uuid64, fwd_uuid64, gnb_pf_status_strings[pf_inet_frame_status], gnb_pf_status_strings[pf_inet_route_status], gnb_pf_status_strings[pf_inet_forwad_status], pf_ctx_st.ip_frame_size); } if ( 1 == gnb_core->conf->if_dump ) { GNB_LOG3(gnb_core->log, GNB_LOG_ID_PF,"----- GNB PF INET END -----\n"); } return; } opengnb-ver1.6.0.a/src/gnb_pf.h000077500000000000000000000201141500454252100162740ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 . */ #ifndef GNB_PF_H #define GNB_PF_H /* packet filter call back order gnb_pf_tun: pf_tun_frame gnb_pf_dump -> gnb_pf_route pf_tun_route gnb_pf_route -> gnb_pf_zip -> gnb_pf_crypto(p2p) pf_tun_fwd gnb_pf_crypto(relay) gnb_pf_inet: pf_inet_frame gnb_pf_crypto(relay) -> gnb_pf_route pf_inet_route gnb_pf_route -> gnb_pf_crypto(p2p) -> gnb_pf_zip pf_inet_fwd gnb_pf_dump -> gnb_pf_route -> gnb_pf_crypto(relay) ┌──────────────────────────┬──────────────────────────────────────────────────────────────────────┐ │ gnb payload header │ gnb payload data │ ├────────┬────────┬────────┼────────────────────────┬───────────────────────────┬─────────────────┤ │ size │ type │sub type│ │ │ relay node id │ ├────────┼────────┼────────┤ gnb route frame header │ ip frame ├─────────────────┤ │ 2 byte │ 1 byte │ 1 byte │ │ │ variable length │ ├────────┴────────┴────────┼────────────────────────┼───────────────────────────┼─────────┬───────┤ │ │ ├─ deflate/inflate segment ─┤ │ │ │ │ ├─ crypto segment ─┤ │ 8byte │ │ │ ├─ relay crypto segmen ─┤ │ └──────────────────────────┴────────────────────────┴─────────────────────────────────────┴───────┘ */ #include #include typedef struct _gnb_core_t gnb_core_t; typedef struct _gnb_payload16_t gnb_payload16_t; typedef struct _gnb_node_t gnb_node_t; typedef struct _gnb_sockaddress_t gnb_sockaddress_t; typedef struct _gnb_pf_ctx_t { int pf_fwd; int pf_status; gnb_uuid_t src_fwd_uuid64; gnb_uuid_t src_uuid64; gnb_uuid_t dst_uuid64; gnb_node_t *src_fwd_node; //转发到下一跳的node gnb_node_t *fwd_node; gnb_node_t *src_node; //最终目的node, 在 tun_frame_cb 中根据 ip header 的 dst 查表获得, //在 inet_frame_cb inet_route_cb 可以根据frame中 dst_uuid 查表获得 gnb_node_t *dst_node; gnb_sockaddress_t *source_node_addr; gnb_payload16_t *fwd_payload; //使用场景是 main pf 定义了 payload 中的报文,需要通过 gnb_pf_ctx_t 报文里的一些字段需要暴露给下一个pf处理 //指向 fwd_payload 中的一个 byte 用于 pf 模块用于标识 payload 类型 unsigned char *pf_type_bits; //指向 fwd_payload 中的ip分组首地址 void *ip_frame; ssize_t ip_frame_size; uint8_t ipproto; uint8_t in_ttl; //in_ttl 在一个 filter cycle 里设置之后不要修改,用于确定 relay_nodeid_array 实际长度 gnb_uuid_t relay_nodeid_array[GNB_MAX_NODE_RELAY]; //网络字节序 uint8_t relay_forwarding; uint8_t unified_forwarding; uint8_t direct_forwarding; uint8_t std_forwarding; uint8_t universal_udp4_relay; }gnb_pf_ctx_t; #define GNB_PF_ERROR 0xFF //当前PF模块过程中出错了,上层调用应该终止这个分组的处理 #define GNB_PF_NEXT 0x00 //当前PF模块处理完成,可以进行一个PF模块的处理,如果是最后一个调用的PF模块, 上层调用 #define GNB_PF_FINISH 0x01 //当前PF模块认为数据分组的处理应该到此为止,上层调用收到这个返回,就不再调用后面的PF模块处理 #define GNB_PF_DROP 0x02 //当前PF模块认为该数据分组应被丢弃 #define GNB_PF_NOROUTE 0x03 //没有找到转发的节点 #define GNB_PF_FWD_INIT 0x0 #define GNB_PF_FWD_TUN 0x1 #define GNB_PF_FWD_INET 0x2 typedef struct _gnb_pf_t gnb_pf_t; typedef void(*gnb_pf_init_cb_t)(gnb_core_t *gnb_core, gnb_pf_t *pf); typedef void(*gnb_pf_conf_cb_t)(gnb_core_t *gnb_core, gnb_pf_t *pf); typedef int(*gnb_pf_chain_cb_t)(gnb_core_t *gnb_core, gnb_pf_t *pf, gnb_pf_ctx_t *pf_ctx); typedef void(*gnb_pf_release_cb_t)(gnb_core_t *gnb_core, gnb_pf_t *pf); typedef struct _gnb_pf_t { const char *name; #define GNB_PF_TYEP_UNSET 0x0 #define GNB_PF_TYEP_DUMP 0x1 #define GNB_PF_TYEP_ROUTE 0x2 #define GNB_PF_TYEP_CRYPTO 0x3 #define GNB_PF_TYEP_COMPRESS 0x4 uint8_t type; void *private_ctx; gnb_pf_init_cb_t pf_init; gnb_pf_conf_cb_t pf_conf; /* tun packet filter step 1: pf_ctx->fwd_payload->data 中存放的是 从tun设备中得到的数据分组, 尽可能不在此 call back 中改变 pf_ctx->fwd_payload->data 的内容使得后面调用的 pf 的处理过程能够访问到原始的来自tun的数据分组 */ gnb_pf_chain_cb_t pf_tun_frame; /* tun packet filter step 2: 在此 call back 中可以确定 payload 的目的节点,对数据分组进行加密,修改 pf_ctx->fwd_payload 的长度 */ gnb_pf_chain_cb_t pf_tun_route; /* tun packet filter step 3: 如果下一跳是 realy 节点,可以在这里做一次加密 */ gnb_pf_chain_cb_t pf_tun_fwd; /* inet packet filter step 1: */ gnb_pf_chain_cb_t pf_inet_frame; /* inet packet filter step 2: */ gnb_pf_chain_cb_t pf_inet_route; /* inet packet filter step 3: 对来自其他节点的 payload 进行中继时可以在此 call back 中对中转的 payload 加密 */ gnb_pf_chain_cb_t pf_inet_fwd; gnb_pf_release_cb_t pf_release; }gnb_pf_t; typedef struct _gnb_pf_array_t { size_t size; size_t num; gnb_pf_t *pf[0]; }gnb_pf_array_t; typedef struct _gnb_pf_core_t { // pf_registered_array gnb_pf_array_t *pf_install_array; gnb_pf_array_t *pf_tun_frame_array; gnb_pf_array_t *pf_tun_route_array; gnb_pf_array_t *pf_tun_fwd_array; gnb_pf_array_t *pf_inet_frame_array; gnb_pf_array_t *pf_inet_route_array; gnb_pf_array_t *pf_inet_fwd_array; }gnb_pf_core_t; void gnb_pf_status_strings_init(); gnb_pf_core_t* gnb_pf_core_init(gnb_heap_t *heap, int size); //初始化 call back 次序 void gnb_pf_core_conf(gnb_core_t *gnb_core, gnb_pf_core_t *pf_core); void gnb_pf_core_release(gnb_core_t *gnb_core, gnb_pf_core_t *pf_core); int gnb_pf_install(gnb_pf_array_t *pf_array, gnb_pf_t *pf); void gnb_pf_init(gnb_core_t *gnb_core, gnb_pf_array_t *pf_array); void gnb_pf_conf(gnb_core_t *gnb_core, gnb_pf_array_t *pf_array); void gnb_pf_tun(gnb_core_t *gnb_core, gnb_pf_core_t *pf_core, gnb_payload16_t *payload); void gnb_pf_inet(gnb_core_t *gnb_core, gnb_pf_core_t *pf_core, gnb_payload16_t *payload, gnb_sockaddress_t *source_node_addr); #endif opengnb-ver1.6.0.a/src/gnb_pf_worker.c000077500000000000000000000205311500454252100176630ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 #include #include #include #include #include "gnb.h" #ifdef __UNIX_LIKE_OS__ #include #include #include #include #include #include #include #endif #ifdef _WIN32 #undef _WIN32_WINNT #define _WIN32_WINNT 0x0600 #include #include #define _POSIX #define __USE_MINGW_ALARM #endif #include #include #include #include "gnb_node.h" #include "gnb_ring_buffer_fixed.h" #include "gnb_worker_queue_data.h" #include "gnb_ur1_frame_type.h" #include "gnb_time.h" #include "gnb_udp.h" #ifdef __UNIX_LIKE_OS__ void bind_socket_if(gnb_core_t *gnb_core); #endif gnb_pf_t* gnb_find_pf_mod_by_name(const char *name); typedef struct _pf_worker_ctx_t{ gnb_core_t *gnb_core; gnb_pf_core_t *pf_core; pthread_t thread_worker; }pf_worker_ctx_t; static void handle_queue(gnb_core_t *gnb_core, gnb_worker_t *pf_worker){ int i; pf_worker_ctx_t *pf_worker_ctx = pf_worker->ctx; gnb_payload16_t *payload_from_tun; gnb_worker_queue_data_t *receive_queue_data; gnb_worker_queue_data_t *send_queue_data; gnb_payload16_t *payload_from_inet; gnb_sockaddress_t *node_addr; int ret; for ( i=0; i<1024; i++ ) { receive_queue_data = gnb_ring_buffer_fixed_pop( pf_worker->ring_buffer_in ); if ( NULL != receive_queue_data ) { payload_from_inet = &receive_queue_data->data.node_in.payload_st; node_addr = &receive_queue_data->data.node_in.node_addr_st; gnb_pf_inet(gnb_core, pf_worker_ctx->pf_core, payload_from_inet, node_addr); gnb_ring_buffer_fixed_pop_submit( pf_worker->ring_buffer_in ); GNB_LOG3(gnb_core->log, GNB_LOG_ID_PF, "[%s] handle queue frome inet\n", pf_worker->name); } send_queue_data = gnb_ring_buffer_fixed_pop( pf_worker->ring_buffer_out ); if ( NULL != send_queue_data ) { payload_from_tun = &send_queue_data->data.node_in.payload_st; gnb_pf_tun(gnb_core, pf_worker_ctx->pf_core, payload_from_tun); gnb_ring_buffer_fixed_pop_submit( pf_worker->ring_buffer_out ); GNB_LOG3(gnb_core->log, GNB_LOG_ID_PF, "[%s] handle queue frome tun\n", pf_worker->name); } if ( NULL == receive_queue_data && NULL == send_queue_data ) { break; } } } static void* thread_worker_func( void *data ) { gnb_worker_t *pf_worker = (gnb_worker_t *)data; pf_worker_ctx_t *pf_worker_ctx = pf_worker->ctx; gnb_core_t *gnb_core = pf_worker_ctx->gnb_core; pf_worker->thread_worker_flag = 1; pf_worker->thread_worker_run_flag = 1; gnb_worker_wait_primary_worker_started(gnb_core); GNB_LOG1(gnb_core->log, GNB_LOG_ID_PF, "start %s success!\n", pf_worker->name); do{ handle_queue(gnb_core, pf_worker); GNB_SLEEP_MILLISECOND(100); }while(pf_worker->thread_worker_flag); pf_worker->thread_worker_run_flag = 0; return NULL; } static void init(gnb_worker_t *gnb_worker, void *ctx){ gnb_core_t *gnb_core = (gnb_core_t *)ctx; pf_worker_ctx_t *pf_worker_ctx = (pf_worker_ctx_t *)gnb_heap_alloc(gnb_core->heap, sizeof(pf_worker_ctx_t)); char *p; gnb_pf_t *find_pf; gnb_pf_t *pf; void *memory; size_t memory_size; memset(pf_worker_ctx, 0, sizeof(pf_worker_ctx_t)); pf_worker_ctx->gnb_core = gnb_core; pf_worker_ctx->pf_core = gnb_pf_core_init(gnb_core->heap, 32); gnb_pf_core_t *pf_core = pf_worker_ctx->pf_core; if ( 1==gnb_core->conf->if_dump ) { find_pf = gnb_find_pf_mod_by_name("gnb_pf_dump"); pf = (gnb_pf_t *)gnb_heap_alloc(gnb_core->heap, sizeof(gnb_pf_t)); *pf = *find_pf; gnb_pf_install(pf_core->pf_install_array, pf); } find_pf = gnb_find_pf_mod_by_name(gnb_core->conf->pf_route); if ( NULL == find_pf ) { GNB_ERROR1(gnb_core->log, GNB_LOG_ID_PF, "pf_route '%s' not exist\n", gnb_core->conf->pf_route); exit(1); } pf = (gnb_pf_t *)gnb_heap_alloc(gnb_core->heap, sizeof(gnb_pf_t)); *pf = *find_pf; gnb_pf_install(pf_core->pf_install_array, pf); if ( 0 != gnb_core->conf->zip_level ) { find_pf = gnb_find_pf_mod_by_name("gnb_pf_zip"); pf = (gnb_pf_t *)gnb_heap_alloc(gnb_core->heap, sizeof(gnb_pf_t)); *pf = *find_pf; gnb_pf_install(pf_core->pf_install_array, pf); } if ( !(GNB_PF_BITS_CRYPTO_XOR & gnb_core->conf->pf_bits) && !(GNB_PF_BITS_CRYPTO_ARC4 & gnb_core->conf->pf_bits) ) { goto skip_crypto; } if ( gnb_core->conf->pf_bits & GNB_PF_BITS_CRYPTO_XOR ) { find_pf = gnb_find_pf_mod_by_name("gnb_pf_crypto_xor"); pf = (gnb_pf_t *)gnb_heap_alloc(gnb_core->heap, sizeof(gnb_pf_t)); *pf = *find_pf; gnb_pf_install(pf_worker_ctx->pf_core->pf_install_array, pf); } if ( gnb_core->conf->pf_bits & GNB_PF_BITS_CRYPTO_ARC4 ) { find_pf = gnb_find_pf_mod_by_name("gnb_pf_crypto_arc4"); pf = (gnb_pf_t *)gnb_heap_alloc(gnb_core->heap, sizeof(gnb_pf_t)); *pf = *find_pf; gnb_pf_install(pf_core->pf_install_array, pf); } skip_crypto: gnb_pf_init(gnb_core, pf_core->pf_install_array); gnb_pf_core_conf(gnb_core, pf_core); gnb_pf_init(gnb_core, pf_core->pf_install_array); gnb_pf_conf(gnb_core, pf_core->pf_install_array); p = gnb_worker->name; gnb_worker->name = (char *)gnb_heap_alloc(gnb_core->heap, 16); snprintf(gnb_worker->name, 16, "%s_%d", p, gnb_core->pf_worker_ring->cur_idx); memory_size = gnb_ring_buffer_fixed_sum_size(sizeof(gnb_payload16_t) + gnb_core->conf->payload_block_size, gnb_core->conf->pf_woker_in_queue_length); memory = gnb_heap_alloc(gnb_core->heap, memory_size); gnb_worker->ring_buffer_in = gnb_ring_buffer_fixed_init(memory, sizeof(gnb_payload16_t) + gnb_core->conf->payload_block_size, gnb_core->conf->pf_woker_in_queue_length); memory_size = gnb_ring_buffer_fixed_sum_size(sizeof(gnb_payload16_t) + gnb_core->conf->payload_block_size, gnb_core->conf->pf_woker_out_queue_length); memory = gnb_heap_alloc(gnb_core->heap, memory_size); gnb_worker->ring_buffer_out = gnb_ring_buffer_fixed_init(memory, sizeof(gnb_payload16_t) + gnb_core->conf->payload_block_size, gnb_core->conf->pf_woker_out_queue_length); gnb_worker->ctx = pf_worker_ctx; GNB_LOG1(gnb_core->log, GNB_LOG_ID_PF, "%s init finish\n", gnb_worker->name); } static void release(gnb_worker_t *gnb_worker){ pf_worker_ctx_t *pf_worker_ctx = (pf_worker_ctx_t *)gnb_worker->ctx; gnb_core_t *gnb_core = pf_worker_ctx->gnb_core; gnb_pf_core_t *pf_core = pf_worker_ctx->pf_core; gnb_pf_core_release(gnb_core, pf_core); } static int start(gnb_worker_t *gnb_worker){ pf_worker_ctx_t *pf_worker_ctx = (pf_worker_ctx_t *)gnb_worker->ctx; pthread_create(&pf_worker_ctx->thread_worker, NULL, thread_worker_func, gnb_worker); pthread_detach(pf_worker_ctx->thread_worker); return 0; } static int stop(gnb_worker_t *gnb_worker){ pf_worker_ctx_t *pf_worker_ctx = (pf_worker_ctx_t *)gnb_worker->ctx; gnb_core_t *gnb_core = pf_worker_ctx->gnb_core; gnb_worker->thread_worker_flag = 0; return 0; } static int notify(gnb_worker_t *gnb_worker){ int ret; pf_worker_ctx_t *pf_worker_ctx = (pf_worker_ctx_t *)gnb_worker->ctx; ret = pthread_kill(pf_worker_ctx->thread_worker,SIGALRM); return 0; } gnb_worker_t gnb_pf_worker_mod = { .name = "gnb_pf_worker", .init = init, .release = release, .start = start, .stop = stop, .notify = notify, .ctx = NULL }; opengnb-ver1.6.0.a/src/gnb_pingpong_frame_type.h000077500000000000000000000053341500454252100217320ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 . */ #ifndef GNB_PINGPONG_FRAME_TYPE_H #define GNB_PINGPONG_FRAME_TYPE_H #include "stdint.h" #include "gnb_core_frame_type_defs.h" #pragma pack(push, 1) typedef struct _node_ping_frame_t { struct __attribute__((__packed__)) ping_frame_data { gnb_uuid_t src_uuid64; //发送方的uuid64 gnb_uuid_t dst_uuid64; //接收方的uuid64 uint64_t src_ts_usec; //发送方的时间戳 /*让 dst 看到自己的 ip 地址,暂时还没启用*/ uint8_t dst_addr4[4]; uint16_t dst_port4; uint8_t dst_addr6[16]; uint16_t dst_port6; unsigned char crypto_seed[64]; unsigned char attachment[128+64]; unsigned char text[32]; }data; unsigned char src_sign[ED25519_SIGN_SIZE]; }__attribute__ ((__packed__)) node_ping_frame_t; #define NODE_PING_FRAME_PAYLOAD_SIZE (sizeof(gnb_payload16_t) + sizeof(node_ping_frame_t)) typedef struct _node_pong_frame_t { struct __attribute__((__packed__)) pong_frame_data { gnb_uuid_t src_uuid64; //发送方的uuid64 gnb_uuid_t dst_uuid64; //接收方的uuid64 uint64_t src_ts_usec; //发送方的时间戳 uint64_t dst_ts_usec; //接收方上一个ping frame带来的时间戳 uint8_t dst_addr4[4]; uint16_t dst_port4; uint8_t dst_addr6[16]; uint16_t dst_port6; unsigned char crypto_seed[64]; unsigned char attachment[128+64]; unsigned char text[32]; }data; unsigned char src_sign[ED25519_SIGN_SIZE]; }__attribute__ ((__packed__)) node_pong_frame_t; #define NODE_PONG_FRAME_PAYLOAD_SIZE (sizeof(gnb_payload16_t) + sizeof(node_pong_frame_t)) #define GNB_NODE_ATTACHMENT_TYPE_TUN_EMPTY 0x0 #define GNB_NODE_ATTACHMENT_TYPE_TUN_SOCKADDRESS 0x1 typedef struct _node_attachment_tun_sockaddress_t { struct in_addr tun_addr4; uint16_t tun_sin_port4; struct in6_addr tun_ipv6_addr; uint16_t tun_sin_port6; uint16_t es_sin_port4; uint16_t es_sin_port6; }__attribute__ ((__packed__)) node_attachment_tun_sockaddress_t; #pragma pack(pop) #endif opengnb-ver1.6.0.a/src/gnb_platform.h000077500000000000000000000015301500454252100175140ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 . */ #ifndef GNB_PLATFORM_H #define GNB_PLATFORM_H #if defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) || defined(__OpenBSD__) #define __UNIX_LIKE_OS__ 1 #endif #endif opengnb-ver1.6.0.a/src/gnb_primary_worker.c000077500000000000000000001066311500454252100207470ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 #include #include #include #include #include "gnb.h" #ifdef __UNIX_LIKE_OS__ #include #include #include #include #include #include #include #endif #ifdef _WIN32 #undef _WIN32_WINNT #define _WIN32_WINNT 0x0600 #include #include #define _POSIX #define __USE_MINGW_ALARM #endif #include #include #include #include "gnb_node.h" #include "gnb_ring_buffer_fixed.h" #include "gnb_worker_queue_data.h" #include "gnb_ur1_frame_type.h" #include "gnb_time.h" #include "gnb_udp.h" #include "gnb_binary.h" #include "crypto/xor/xor.h" #ifdef __UNIX_LIKE_OS__ void bind_socket_if(gnb_core_t *gnb_core); #endif gnb_pf_t* gnb_find_pf_mod_by_name(const char *name); typedef struct _primary_worker_ctx_t{ gnb_core_t *gnb_core; gnb_pf_core_t *pf_core; #ifdef __UNIX_LIKE_OS__ pthread_t tun_udp_loop_thread; #endif #ifdef _WIN32 pthread_t tun_loop_thread; pthread_t udp_loop_thread; #endif }primary_worker_ctx_t; #pragma pack(push, 1) typedef struct _gnb_ur0_frame_head_t { uint8_t dst_addr4[4]; uint16_t dst_port4; unsigned char passcode[4]; } __attribute__ ((__packed__)) gnb_ur0_frame_head_t; #pragma pack(pop) gnb_worker_t * select_pf_worker(gnb_core_t *gnb_core){ gnb_worker_t *pf_worker = NULL; pf_worker = gnb_core->pf_worker_ring->worker[ gnb_core->pf_worker_ring->cur_idx ]; gnb_core->pf_worker_ring->cur_idx++; if ( gnb_core->pf_worker_ring->cur_idx >= gnb_core->pf_worker_ring->size ) { gnb_core->pf_worker_ring->cur_idx = 0; } return pf_worker; } void gnb_send_ur0_frame(gnb_core_t *gnb_core, gnb_node_t *dst_node, gnb_payload16_t *payload){ unsigned char buffer[gnb_core->conf->payload_block_size]; gnb_payload16_t *fwd_payload = (gnb_payload16_t *)buffer; gnb_address_t *dst_address = gnb_select_available_address4(gnb_core, dst_node); gnb_address_t node_address_st; if( NULL == dst_address ) { if ( 0 != dst_node->udp_sockaddr4.sin_port ) { node_address_st.type = AF_INET; memcpy(&node_address_st.m_address4, &dst_node->udp_sockaddr4.sin_addr.s_addr, 4); node_address_st.port = dst_node->udp_sockaddr4.sin_port; dst_address = &node_address_st; } } if ( NULL == dst_address ) { return; } gnb_address_t *fwd_address = &gnb_core->fwdu0_address_ring.address_list->array[0]; gnb_ur0_frame_head_t *ur0_frame_head = (gnb_ur0_frame_head_t *)fwd_payload->data; fwd_payload->type = GNB_PAYLOAD_TYPE_UR0; memcpy(ur0_frame_head->dst_addr4, &dst_address->m_address4, 4); ur0_frame_head->dst_port4 = dst_address->port; memcpy(ur0_frame_head->passcode, gnb_core->conf->crypto_passcode, 4); uint16_t payload_size = gnb_payload16_size(payload); memcpy(fwd_payload->data + sizeof(gnb_ur0_frame_head_t), payload, payload_size); gnb_payload16_set_data_len(fwd_payload, sizeof(gnb_ur0_frame_head_t) + payload_size); gnb_send_to_address(gnb_core, fwd_address, fwd_payload); if ( 1==gnb_core->conf->if_dump ) { GNB_LOG3(gnb_core->log, GNB_LOG_ID_MAIN_WORKER, "send ur0 local =>[%s]=>dst_addr[%s:%d]\n", GNB_IP_PORT_STR1(fwd_address), GNB_ADDR4STR2(ur0_frame_head->dst_addr4), ntohs(ur0_frame_head->dst_port4)); } } static void handle_ur0_frame(gnb_core_t *gnb_core, gnb_payload16_t *payload, gnb_sockaddress_t *source_node_addr){ gnb_ur0_frame_head_t *ur0_frame_head = (gnb_ur0_frame_head_t *)payload->data; gnb_address_t dst_address_st; dst_address_st.type = AF_INET; memcpy(&dst_address_st.address.addr4, ur0_frame_head->dst_addr4, 4); dst_address_st.port = ur0_frame_head->dst_port4; if ( 0 != memcmp(ur0_frame_head->passcode, gnb_core->conf->crypto_passcode, 4) ) { if ( 1==gnb_core->conf->if_dump ) { GNB_LOG3(gnb_core->log, GNB_LOG_ID_MAIN_WORKER, "handle ur0 =>[%s] passcode invalid\n", GNB_IP_PORT_STR1(&dst_address_st) ); } return; } gnb_payload16_t *fwd_payload = (gnb_payload16_t *)(payload->data + sizeof(gnb_ur0_frame_head_t)); gnb_send_to_address(gnb_core, &dst_address_st, fwd_payload); if ( 1==gnb_core->conf->if_dump ) { GNB_LOG3(gnb_core->log, GNB_LOG_ID_MAIN_WORKER, "handle ur0 %s => %s\n", GNB_SOCKETADDRSTR1(source_node_addr), GNB_IP_PORT_STR1(&dst_address_st) ); } } static void handle_ur1_frame(gnb_core_t *gnb_core, gnb_payload16_t *payload, gnb_sockaddress_t *node_addr){ gnb_address_t ur1_address_st; gnb_uuid_t src_uuid64; gnb_uuid_t dst_uuid64; gnb_node_t *src_node; gnb_node_t *dst_node; uint16_t data_size; unsigned char *ur1_data; uint16_t ur1_data_size; unsigned char verifycode[4]; #define GNB_UR1_SOURCE_UNSET 0 //payload来自 App #define GNB_UR1_SOURCE_APP 1 //payload来自 gnb node #define GNB_UR1_SOURCE_NODE 2 int ur1_source = GNB_UR1_SOURCE_UNSET; data_size = GNB_PAYLOAD16_DATA_SIZE(payload); if ( data_size <= sizeof(gnb_ur1_frame_head_t) ) { GNB_LOG3(gnb_core->log, GNB_LOG_ID_MAIN_WORKER, "UR1 frame frome %s payload size error!\n", GNB_SOCKETADDRSTR1(node_addr)); return; } gnb_ur1_frame_head_t *ur1_frame_head = (gnb_ur1_frame_head_t *)payload->data; if ( ur1_frame_head->ttl > 2 ) { GNB_LOG3(gnb_core->log, GNB_LOG_ID_MAIN_WORKER, "UR1 frame frome %s payload ttl=%d error!\n", ur1_frame_head->ttl, GNB_SOCKETADDRSTR1(node_addr)); return; } if ( 0 != memcmp(ur1_frame_head->passcode, gnb_core->conf->crypto_passcode, 4) ) { GNB_LOG3(gnb_core->log, GNB_LOG_ID_MAIN_WORKER, "UR1 frame frome %s payload passcode error!\n", GNB_SOCKETADDRSTR1(node_addr)); return; } dst_uuid64 = gnb_ntohll(ur1_frame_head->dst_uuid64); if ( 0==dst_uuid64 ) { GNB_LOG3(gnb_core->log, GNB_LOG_ID_MAIN_WORKER, "UR1 frame frome %s payload dst_node=%llu error!\n", GNB_SOCKETADDRSTR1(node_addr), dst_uuid64); return; } dst_node = (gnb_node_t *)GNB_HASH32_UINT64_GET_PTR(gnb_core->uuid_node_map, dst_uuid64); if ( NULL==dst_node ) { GNB_LOG3(gnb_core->log, GNB_LOG_ID_MAIN_WORKER, "UR1 frame frome %s payload dst_node=%llu not found!\n", GNB_SOCKETADDRSTR1(node_addr), dst_uuid64); return; } // 0==src_uuid64 说明 payload 来自应用端, 需要为 payload 设置 src_uuid64,src_addr,ttl if ( 0 == ur1_frame_head->src_uuid64 ) { ur1_frame_head->src_uuid64 = gnb_htonll(gnb_core->local_node->uuid64); ur1_frame_head->ttl = 2; if ( AF_INET6 == node_addr->addr_type ) { //IPV6:bit=0 payload->sub_type &= ~(GNB_PAYLOAD_SUB_TYPE_UR1_SRC_ADDRESS4); memcpy(ur1_frame_head->src_addr, &node_addr->addr.in6.sin6_addr, 16); ur1_frame_head->src_port = node_addr->addr.in6.sin6_port; GNB_LOG3(gnb_core->log, GNB_LOG_ID_MAIN_WORKER, "UR1 frame frome %s dst_node=%llu src_uuid64=0 set src_addr=%s:%d\n", GNB_SOCKETADDRSTR1(node_addr), dst_uuid64, GNB_ADDR6STR2(ur1_frame_head->src_addr), ntohs(ur1_frame_head->src_port)); } else if ( AF_INET == node_addr->addr_type ) { //IPV4:bit=1 payload->sub_type |= GNB_PAYLOAD_SUB_TYPE_UR1_SRC_ADDRESS4; memcpy(ur1_frame_head->src_addr, &node_addr->addr.in.sin_addr, 4); ur1_frame_head->src_port = node_addr->addr.in.sin_port; GNB_LOG3(gnb_core->log, GNB_LOG_ID_MAIN_WORKER, "UR1 frame frome %s dst_node=%llu src_uuid64=0 set src_addr=%s:%d\n", GNB_SOCKETADDRSTR1(node_addr), dst_uuid64, GNB_ADDR4STR2(ur1_frame_head->src_addr), ntohs(ur1_frame_head->src_port)); } else { GNB_LOG3(gnb_core->log, GNB_LOG_ID_MAIN_WORKER, "UR1 frame frome %s dst_node=%llu in addr_type error\n", GNB_SOCKETADDRSTR1(node_addr), dst_uuid64); return; } ur1_source = GNB_UR1_SOURCE_APP; } else { ur1_source = GNB_UR1_SOURCE_NODE; if ( ur1_frame_head->ttl > 0 ) { ur1_frame_head->ttl--; } } src_uuid64 = gnb_ntohll(ur1_frame_head->src_uuid64); src_node = (gnb_node_t *)GNB_HASH32_UINT64_GET_PTR(gnb_core->uuid_node_map, src_uuid64); if ( NULL==src_node ) { GNB_LOG3(gnb_core->log, GNB_LOG_ID_MAIN_WORKER, "UR1 frame frome %s payload src_node=%llu not found!\n", GNB_SOCKETADDRSTR1(node_addr), src_uuid64); return; } ur1_data = payload->data + sizeof(gnb_ur1_frame_head_t); ur1_data_size = data_size - sizeof(gnb_ur1_frame_head_t); //payload 来自一个 gnb node 或 App 设置目的节点就是本地节点 if ( dst_uuid64 == gnb_core->local_node->uuid64 ) { memset(&ur1_address_st, 0, sizeof(gnb_address_t)); ur1_address_st.port = ur1_frame_head->dst_port; if ( !(payload->sub_type & GNB_PAYLOAD_SUB_TYPE_UR1_DST_ADDRESS4) ) { //IPV6 ur1_address_st.type = AF_INET6; memcpy(&ur1_address_st.m_address6, ur1_frame_head->dst_addr, 16); GNB_LOG3(gnb_core->log, GNB_LOG_ID_MAIN_WORKER, "UR1 frame frome %s src_uuid=%llu dst_node=%llu payload to host dst=%s:%d\n", GNB_SOCKETADDRSTR1(node_addr), gnb_ntohll(ur1_frame_head->src_uuid64), dst_uuid64, GNB_ADDR6STR2(&ur1_address_st.m_address6), ntohs(ur1_address_st.port)); } else { //IPV4 ur1_address_st.type = AF_INET; memcpy(&ur1_address_st.m_address4, ur1_frame_head->dst_addr, 4); GNB_LOG3(gnb_core->log, GNB_LOG_ID_MAIN_WORKER, "UR1 frame frome %s src_uuid=%llu dst_node=%llu payload to host dst=%s:%d\n", GNB_SOCKETADDRSTR1(node_addr), gnb_ntohll(ur1_frame_head->src_uuid64), dst_uuid64, GNB_ADDR4STR2(&ur1_address_st.m_address4), ntohs(ur1_address_st.port)); } if ( ur1_frame_head->src_uuid64 != ur1_frame_head->dst_uuid64) { //解密 xor_crypto(src_node->crypto_key, (unsigned char *)ur1_data, ur1_data_size); verifycode[0] = ur1_data[0]; verifycode[1] = ur1_data[1]; verifycode[2] = ur1_data[ur1_data_size-2]; verifycode[3] = ur1_data[ur1_data_size-1]; if ( 0 != memcmp(ur1_frame_head->verifycode, verifycode, 4) ) { GNB_LOG3(gnb_core->log,GNB_LOG_ID_MAIN_WORKER, "UR1 frame frome %s payload verifycode error by crypto_key!\n", GNB_SOCKETADDRSTR1(node_addr)); //尝试用旧通信密钥解密 xor_crypto(src_node->pre_crypto_key, (unsigned char *)ur1_data, ur1_data_size); verifycode[0] = ur1_data[0]; verifycode[1] = ur1_data[1]; verifycode[2] = ur1_data[ur1_data_size-2]; verifycode[3] = ur1_data[ur1_data_size-1]; if ( 0 != memcmp(ur1_frame_head->verifycode, verifycode, 4) ) { GNB_LOG3(gnb_core->log,GNB_LOG_ID_MAIN_WORKER, "UR1 frame frome %s payload verifycode error by pre_crypto_key!\n", GNB_SOCKETADDRSTR1(node_addr)); return; } } } //payload 转发到指定 host and port if ( payload->sub_type & GNB_PAYLOAD_SUB_TYPE_UR1_HEADER ) { gnb_send_to_address(gnb_core, &ur1_address_st, payload); GNB_LOG3(gnb_core->log,GNB_LOG_ID_MAIN_WORKER, "UR1 frame payload relay to %s whith frame header\n", GNB_IP_PORT_STR1(&ur1_address_st) ); } else { //skip frame header gnb_send_udata_to_address(gnb_core,&ur1_address_st, payload->data + sizeof(gnb_ur1_frame_head_t), data_size - sizeof(gnb_ur1_frame_head_t)); GNB_LOG3(gnb_core->log,GNB_LOG_ID_MAIN_WORKER, "UR1 frame payload relay to %s whithout frame header\n", GNB_IP_PORT_STR1(&ur1_address_st) ); } return; } //payload 转发到指定 gnb node if ( GNB_UR1_SOURCE_APP == ur1_source && dst_uuid64 != gnb_core->local_node->uuid64 ) { //第一个gnb node,执行加密 ur1_frame_head->verifycode[0] = ur1_data[0]; ur1_frame_head->verifycode[1] = ur1_data[1]; ur1_frame_head->verifycode[2] = ur1_data[ur1_data_size-2]; ur1_frame_head->verifycode[3] = ur1_data[ur1_data_size-1]; xor_crypto(dst_node->crypto_key, ur1_data, ur1_data_size); gnb_std_uf_forward_payload_to_node(gnb_core, dst_node, payload); GNB_LOG3(gnb_core->log,GNB_LOG_ID_MAIN_WORKER, "UR1 frame frome %s to dst node=%llu payload\n", GNB_SOCKETADDRSTR1(node_addr), dst_uuid64); return; } else if ( GNB_UR1_SOURCE_NODE == ur1_source && dst_uuid64 != gnb_core->local_node->uuid64 ) { if ( 0==ur1_frame_head->ttl ) { GNB_LOG3(gnb_core->log, GNB_LOG_ID_MAIN_WORKER, "UR1 frame frome %s payload ttl=%d error!\n", ur1_frame_head->ttl, GNB_SOCKETADDRSTR1(node_addr)); return; } gnb_std_uf_forward_payload_to_node(gnb_core, dst_node, payload); GNB_LOG3(gnb_core->log,GNB_LOG_ID_MAIN_WORKER, "UR1 frame from %s src node=%d to dst node=%llu payload relay!\n", GNB_SOCKETADDRSTR1(node_addr), gnb_core->local_node->uuid64, dst_uuid64); } else { GNB_LOG3(gnb_core->log,GNB_LOG_ID_MAIN_WORKER, "UR1 frame from %s src node=%d to dst node=%llu ur1_source=%d, ttl==%d payload error!\n", GNB_SOCKETADDRSTR1(node_addr), gnb_core->local_node->uuid64, dst_uuid64, ur1_source, ur1_frame_head->ttl); } } static gnb_worker_queue_data_t* make_worker_receive_queue_data(gnb_worker_t *worker, gnb_sockaddress_t *node_addr, uint8_t socket_idx, gnb_payload16_t *payload){ gnb_worker_queue_data_t *receive_queue_data = (gnb_worker_queue_data_t *)gnb_ring_buffer_fixed_push(worker->ring_buffer_in); if ( NULL == receive_queue_data ) { return NULL; } receive_queue_data->type = GNB_WORKER_QUEUE_DATA_TYPE_NODE_IN; memcpy(&receive_queue_data->data.node_in.node_addr_st, node_addr, sizeof(gnb_sockaddress_t)); receive_queue_data->data.node_in.socket_idx = socket_idx; memcpy(&receive_queue_data->data.node_in.payload_st, payload, gnb_payload16_size(payload)); return receive_queue_data; } static gnb_worker_queue_data_t* make_worker_send_queue_data(gnb_worker_t *worker, gnb_payload16_t *payload){ gnb_worker_queue_data_t *send_queue_data = (gnb_worker_queue_data_t *)gnb_ring_buffer_fixed_push(worker->ring_buffer_out); if ( NULL == send_queue_data ) { return NULL; } send_queue_data->type = GNB_WORKER_QUEUE_DATA_TYPE_NODE_OUT; memcpy(&send_queue_data->data.node_in.payload_st, payload, gnb_payload16_size(payload)); return send_queue_data; } static void handle_udp(gnb_core_t *gnb_core, gnb_pf_core_t *pf_core, uint8_t socket_idx, int af){ ssize_t n_recv; uint16_t payload_size; gnb_sockaddress_t node_addr_st; gnb_worker_t *pf_worker; gnb_worker_queue_data_t *receive_queue_data; gnb_payload16_t *inet_payload; if ( !gnb_core->conf->activate_tun ) { inet_payload = gnb_core->inet_payload; goto skip_tun; } if ( gnb_core->pf_worker_ring->size == 0 ) { inet_payload = gnb_core->inet_payload; } else { pf_worker = select_pf_worker(gnb_core); receive_queue_data = (gnb_worker_queue_data_t *)gnb_ring_buffer_fixed_push(pf_worker->ring_buffer_in); if ( NULL == receive_queue_data ) { return; } inet_payload = &receive_queue_data->data.node_in.payload_st; } skip_tun: switch (af) { case AF_INET6: node_addr_st.socklen = sizeof(struct sockaddr_in6); n_recv = recvfrom(gnb_core->udp_ipv6_sockets[socket_idx], (void *)inet_payload, gnb_core->conf->payload_block_size, 0, (struct sockaddr *)&node_addr_st.addr.in6, &node_addr_st.socklen); node_addr_st.addr_type = AF_INET6; break; case AF_INET: node_addr_st.socklen = sizeof(struct sockaddr_in); n_recv = recvfrom(gnb_core->udp_ipv4_sockets[socket_idx], (void *)inet_payload, gnb_core->conf->payload_block_size, 0, (struct sockaddr *)&node_addr_st.addr.in, &node_addr_st.socklen); node_addr_st.addr_type = AF_INET; break; default: n_recv = 0; break; } if ( n_recv <= 0 ) { goto finish; } if ( 1 == gnb_core->conf->if_dump ) { GNB_LOG3(gnb_core->log, GNB_LOG_ID_CORE, "Payload INET in buffer[%s..]\n", GNB_HEX2_BYTE256((void *)inet_payload)); } node_addr_st.protocol = SOCK_DGRAM; payload_size = gnb_payload16_size(inet_payload); if ( payload_size != n_recv ) { GNB_LOG3(gnb_core->log, GNB_LOG_ID_MAIN_WORKER, "handle_udp n_recv=%lu payload_size=%u payload invalid!\n", n_recv, payload_size); goto finish; } if ( 1 == gnb_core->conf->activate_tun && GNB_PAYLOAD_TYPE_IPFRAME == inet_payload->type ) { if ( gnb_core->pf_worker_ring->size == 0 ) { gnb_pf_inet(gnb_core, pf_core, inet_payload, &node_addr_st); } else { receive_queue_data->type = GNB_WORKER_QUEUE_DATA_TYPE_NODE_IN; memcpy(&receive_queue_data->data.node_in.node_addr_st, &node_addr_st, sizeof(gnb_sockaddress_t)); receive_queue_data->data.node_in.socket_idx = socket_idx; gnb_ring_buffer_fixed_push_submit(pf_worker->ring_buffer_in); pf_worker->notify(pf_worker); } goto finish; } //收到 index 类型的paload 就放到 index_worker 或 index_service_worker queue 中 if( GNB_PAYLOAD_TYPE_INDEX == inet_payload->type ) { switch ( inet_payload->sub_type ) { case PAYLOAD_SUB_TYPE_POST_ADDR : case PAYLOAD_SUB_TYPE_REQUEST_ADDR : if ( 0 == gnb_core->conf->activate_index_service_worker ) { goto finish; } receive_queue_data = make_worker_receive_queue_data(gnb_core->index_service_worker, &node_addr_st, socket_idx, inet_payload); if ( NULL == receive_queue_data ) { //ringbuffer is full GNB_LOG3(gnb_core->log, GNB_LOG_ID_MAIN_WORKER, "handle_udp index_service_worker ringbuffer is full!\n"); goto finish; } gnb_ring_buffer_fixed_push_submit(gnb_core->index_service_worker->ring_buffer_in); gnb_core->index_service_worker->notify(gnb_core->index_service_worker); break; case PAYLOAD_SUB_TYPE_ECHO_ADDR : case PAYLOAD_SUB_TYPE_PUSH_ADDR : case PAYLOAD_SUB_TYPE_DETECT_ADDR : if ( 0 == gnb_core->conf->activate_index_worker ) { goto finish; } receive_queue_data = make_worker_receive_queue_data(gnb_core->index_worker, &node_addr_st, socket_idx, inet_payload); if ( NULL == receive_queue_data ) { //ringbuffer is full GNB_LOG3(gnb_core->log, GNB_LOG_ID_MAIN_WORKER, "handle_udp index_worker ringbuffer is full!\n"); goto finish; } gnb_ring_buffer_fixed_push_submit(gnb_core->index_worker->ring_buffer_in); gnb_core->index_worker->notify(gnb_core->index_worker); break; default : break; } goto finish; } //收到 node 类型的paload 就放到 node_worker queue 中 if ( GNB_PAYLOAD_TYPE_NODE == inet_payload->type ) { if ( 0 == gnb_core->conf->activate_node_worker ) { goto finish; } receive_queue_data = make_worker_receive_queue_data(gnb_core->node_worker, &node_addr_st, socket_idx, inet_payload); if ( NULL == receive_queue_data ) { //ringbuffer is full GNB_LOG3(gnb_core->log, GNB_LOG_ID_MAIN_WORKER, "handle_udp node_worker ringbuffer is full!\n"); goto finish; } gnb_ring_buffer_fixed_push_submit(gnb_core->node_worker->ring_buffer_in); gnb_core->node_worker->notify(gnb_core->node_worker); goto finish; } if ( GNB_PAYLOAD_TYPE_UR1 == inet_payload->type && 1 == gnb_core->conf->universal_relay1 ) { handle_ur1_frame(gnb_core, inet_payload, &node_addr_st); goto finish; } if ( GNB_PAYLOAD_TYPE_UR0 == inet_payload->type && 1 == gnb_core->conf->universal_relay0 ) { handle_ur0_frame(gnb_core, inet_payload, &node_addr_st); goto finish; } finish: return; } static int handle_tun(gnb_core_t *gnb_core, gnb_pf_core_t *pf_core){ ssize_t rlen; gnb_worker_t *pf_worker; gnb_worker_queue_data_t *send_queue_data; //tun模式下这里得到的payload是ip分组, tap模式下是以太网分组,现在都是tun模式 rlen = gnb_core->drv->read_tun(gnb_core, gnb_core->tun_payload->data + gnb_core->tun_payload_offset, gnb_core->conf->payload_block_size); if ( rlen<=0 ) { goto finish; } if ( 1 == gnb_core->conf->if_dump ) { GNB_LOG3(gnb_core->log, GNB_LOG_ID_CORE, "Payload TUN out buffer[%s..]\n", GNB_HEX2_BYTE128((void *)(gnb_core->tun_payload->data + gnb_core->tun_payload_offset))); } gnb_payload16_set_size(gnb_core->tun_payload, GNB_PAYLOAD16_HEAD_SIZE + gnb_core->tun_payload_offset + rlen); if ( gnb_core->pf_worker_ring->size == 0 ) { gnb_pf_tun(gnb_core, pf_core, gnb_core->tun_payload); } else { pf_worker = select_pf_worker(gnb_core); send_queue_data = make_worker_send_queue_data(pf_worker, gnb_core->tun_payload); if ( NULL == send_queue_data ) { //ringbuffer is full goto finish; } gnb_ring_buffer_fixed_push_submit(pf_worker->ring_buffer_out); pf_worker->notify(pf_worker); } finish: return rlen; } #ifdef _WIN32 static void* tun_loop_thread_func( void *data ) { gnb_worker_t *gnb_worker = (gnb_worker_t *)data; primary_worker_ctx_t *primary_worker_ctx = gnb_worker->ctx; gnb_core_t *gnb_core = primary_worker_ctx->gnb_core; gnb_pf_core_t *pf_core = primary_worker_ctx->pf_core; ssize_t rlen; gnb_core->loop_flag = 1; while ( gnb_core->loop_flag ) { rlen = gnb_core->drv->read_tun(gnb_core, gnb_core->tun_payload->data + gnb_core->tun_payload_offset, gnb_core->conf->payload_block_size); if ( rlen<=0 ) { continue; } if ( 1 == gnb_core->conf->if_dump ) { GNB_LOG3(gnb_core->log, GNB_LOG_ID_CORE, "Payload TUN out buffer[%s..]\n", GNB_HEX2_BYTE128((void *)(gnb_core->tun_payload->data + gnb_core->tun_payload_offset))); } gnb_payload16_set_size(gnb_core->tun_payload, GNB_PAYLOAD16_HEAD_SIZE + gnb_core->tun_payload_offset + rlen); gnb_pf_tun(gnb_core, pf_core, gnb_core->tun_payload); } return NULL; } static void* udp_loop_thread_func( void *data ) { gnb_worker_t *gnb_worker = (gnb_worker_t *)data; primary_worker_ctx_t *primary_worker_ctx = gnb_worker->ctx; gnb_core_t *gnb_core = primary_worker_ctx->gnb_core; gnb_pf_core_t *pf_core = primary_worker_ctx->pf_core; int n_ready; struct timeval timeout; fd_set readfds; fd_set allset; FD_ZERO(&readfds); FD_ZERO(&allset); int maxfd = 0; int i; if ( gnb_core->conf->udp_socket_type & GNB_ADDR_TYPE_IPV6 ) { for ( i=0; i < gnb_core->conf->udp6_socket_num; i++ ) { FD_SET(gnb_core->udp_ipv6_sockets[i], &allset); if ( gnb_core->udp_ipv6_sockets[i] > maxfd ) { maxfd = gnb_core->udp_ipv6_sockets[i]; } } } if ( gnb_core->conf->udp_socket_type & GNB_ADDR_TYPE_IPV4 ) { for ( i=0; i < gnb_core->conf->udp4_socket_num; i++ ) { FD_SET(gnb_core->udp_ipv4_sockets[i], &allset); if ( gnb_core->udp_ipv4_sockets[i] > maxfd ) { maxfd = gnb_core->udp_ipv4_sockets[i]; } } } int ret = 0; gnb_worker->thread_worker_flag = 1; gnb_worker->thread_worker_run_flag = 1; gnb_core->loop_flag = 1; uint64_t pre_usec = 0l; while (gnb_core->loop_flag) { readfds = allset; //由于在Windows下pthread_kill不起作用,因此不能依靠信号打断 select,因此把select的超时时间设短 timeout.tv_sec = 0l; timeout.tv_usec = 10000l; n_ready = select( maxfd + 1, &readfds, NULL, NULL, &timeout ); if ( -1 == n_ready ) { if ( EINTR == errno ) { //udp_loop_thread_func 被信号打断,可能队列里面被投放了数据 continue; } else { break; } } if ( gnb_core->conf->udp_socket_type & GNB_ADDR_TYPE_IPV6 ) { for ( i=0; iconf->udp6_socket_num; i++ ) { if ( FD_ISSET( gnb_core->udp_ipv6_sockets[i], &readfds ) ) { handle_udp(gnb_core, pf_core, i, AF_INET6); } } } if ( gnb_core->conf->udp_socket_type & GNB_ADDR_TYPE_IPV4 ) { for ( i=0; iconf->udp4_socket_num; i++ ) { if ( FD_ISSET( gnb_core->udp_ipv4_sockets[i], &readfds ) ) { handle_udp(gnb_core, pf_core, i, AF_INET); } } } }//while() if ( (gnb_core->conf->udp_socket_type & GNB_ADDR_TYPE_IPV6) ) { for ( i=0; iconf->udp6_socket_num; i++ ) { FD_CLR(gnb_core->udp_ipv6_sockets[i], &allset); } } if ( (gnb_core->conf->udp_socket_type & GNB_ADDR_TYPE_IPV4) ) { for ( i=0; iconf->udp4_socket_num; i++ ) { FD_CLR(gnb_core->udp_ipv4_sockets[i], &allset); } } return NULL; } #endif #ifdef __UNIX_LIKE_OS__ static void* tun_udp_loop_thread_func(void *data){ gnb_worker_t *gnb_worker = (gnb_worker_t *)data; primary_worker_ctx_t *primary_worker_ctx = gnb_worker->ctx; gnb_core_t *gnb_core = primary_worker_ctx->gnb_core; gnb_pf_core_t *pf_core = primary_worker_ctx->pf_core; int n_ready; struct timeval timeout; fd_set readfds; fd_set allset; FD_ZERO(&readfds); FD_ZERO(&allset); int maxfd = 0; if ( gnb_core->conf->activate_tun ) { if ( -1 == gnb_core->tun_fd ) { GNB_LOG3(gnb_core->log, GNB_LOG_ID_MAIN_WORKER, "tun_fd[%d] err\n", gnb_core->tun_fd); exit(1); } FD_SET(gnb_core->tun_fd, &allset); maxfd = gnb_core->tun_fd; } int i; if ( gnb_core->conf->udp_socket_type & GNB_ADDR_TYPE_IPV6 ) { for ( i=0; iconf->udp6_socket_num; i++ ) { FD_SET(gnb_core->udp_ipv6_sockets[i], &allset); if ( gnb_core->udp_ipv6_sockets[i] > maxfd ) { maxfd = gnb_core->udp_ipv6_sockets[i]; } } } if ( gnb_core->conf->udp_socket_type & GNB_ADDR_TYPE_IPV4 ) { for ( i=0; iconf->udp4_socket_num; i++ ) { FD_SET(gnb_core->udp_ipv4_sockets[i], &allset); if ( gnb_core->udp_ipv4_sockets[i] > maxfd ) { maxfd = gnb_core->udp_ipv4_sockets[i]; } } } int ret = 0; gnb_core->loop_flag = 1; gnb_worker->thread_worker_flag = 1; gnb_worker->thread_worker_run_flag = 1; static unsigned long c = 0; GNB_LOG1(gnb_core->log, GNB_LOG_ID_MAIN_WORKER, "start %s success!\n", gnb_worker->name); while ( gnb_core->loop_flag ) { readfds = allset; timeout.tv_sec = 1l; timeout.tv_usec = 10000l; n_ready = select( maxfd + 1, &readfds, NULL, NULL, &timeout ); if ( -1 == n_ready ) { if ( EINTR == errno ) { //检查一下有没到这里 //被信号打断,可能队列里面被投放了数据 continue; } else { break; } } if ( gnb_core->conf->udp_socket_type & GNB_ADDR_TYPE_IPV6 ) { for ( i=0; i < gnb_core->conf->udp6_socket_num; i++ ) { if ( FD_ISSET( gnb_core->udp_ipv6_sockets[i], &readfds ) ) { handle_udp(gnb_core, pf_core, i, AF_INET6); } } } if ( gnb_core->conf->udp_socket_type & GNB_ADDR_TYPE_IPV4 ) { for ( i=0; i < gnb_core->conf->udp4_socket_num; i++ ) { if ( FD_ISSET( gnb_core->udp_ipv4_sockets[i], &readfds ) ) { handle_udp(gnb_core, pf_core, i, AF_INET); } } } if ( gnb_core->conf->activate_tun ) { if ( FD_ISSET( gnb_core->tun_fd, &readfds ) ) { handle_tun(gnb_core, pf_core); } } }//while() if ( (gnb_core->conf->udp_socket_type & GNB_ADDR_TYPE_IPV6) ) { for (i=0; iconf->udp6_socket_num; i++) { FD_CLR(gnb_core->udp_ipv6_sockets[i], &allset); } } if ( (gnb_core->conf->udp_socket_type & GNB_ADDR_TYPE_IPV4) ) { for (i=0; iconf->udp4_socket_num; i++) { FD_CLR(gnb_core->udp_ipv4_sockets[i], &allset); } } if ( gnb_core->conf->activate_tun ) { FD_CLR(gnb_core->tun_fd, &allset); } return NULL; } #endif static void init(gnb_worker_t *gnb_worker, void *ctx){ gnb_core_t *gnb_core = (gnb_core_t *)ctx; primary_worker_ctx_t *primary_worker_ctx = (primary_worker_ctx_t *)gnb_heap_alloc(gnb_core->heap, sizeof(primary_worker_ctx_t)); memset(primary_worker_ctx, 0, sizeof(primary_worker_ctx_t)); //没有线程需要投递数据到这个线程 gnb_worker->ring_buffer_in = NULL; gnb_worker->ring_buffer_out = NULL; primary_worker_ctx->gnb_core = (gnb_core_t *)ctx; gnb_worker->ctx = primary_worker_ctx; primary_worker_ctx->pf_core = gnb_pf_core_init(gnb_core->heap, 32); gnb_pf_core_t *pf_core = primary_worker_ctx->pf_core; gnb_pf_t *pf; if ( 1==gnb_core->conf->if_dump ) { pf = gnb_find_pf_mod_by_name("gnb_pf_dump"); gnb_pf_install(primary_worker_ctx->pf_core->pf_install_array, pf); } pf = gnb_find_pf_mod_by_name(gnb_core->conf->pf_route); if ( NULL == pf ) { GNB_ERROR1(gnb_core->log, GNB_LOG_ID_CORE, "pf_route '%s' not exist\n", gnb_core->conf->pf_route); exit(1); } gnb_pf_install(pf_core->pf_install_array, pf); if ( 0 != gnb_core->conf->zip_level ) { pf = gnb_find_pf_mod_by_name("gnb_pf_zip"); gnb_pf_install(pf_core->pf_install_array, pf); } if ( !(GNB_PF_BITS_CRYPTO_XOR & gnb_core->conf->pf_bits) && !(GNB_PF_BITS_CRYPTO_ARC4 & gnb_core->conf->pf_bits) ) { goto skip_crypto; } if ( gnb_core->conf->pf_bits & GNB_PF_BITS_CRYPTO_XOR ) { pf = gnb_find_pf_mod_by_name("gnb_pf_crypto_xor"); gnb_pf_install(pf_core->pf_install_array, pf); } if ( gnb_core->conf->pf_bits & GNB_PF_BITS_CRYPTO_ARC4 ) { pf = gnb_find_pf_mod_by_name("gnb_pf_crypto_arc4"); gnb_pf_install(pf_core->pf_install_array, pf); } skip_crypto: gnb_pf_core_conf(gnb_core, pf_core); gnb_pf_init(gnb_core, pf_core->pf_install_array); gnb_pf_conf(gnb_core, pf_core->pf_install_array); GNB_LOG1(gnb_core->log, GNB_LOG_ID_MAIN_WORKER, "%s init finish\n", gnb_worker->name); } static void release(gnb_worker_t *gnb_worker){ primary_worker_ctx_t *primary_worker_ctx = (primary_worker_ctx_t *)gnb_worker->ctx; gnb_core_t *gnb_core = primary_worker_ctx->gnb_core; gnb_pf_core_t *pf_core = primary_worker_ctx->pf_core; gnb_pf_core_release(gnb_core, pf_core); } static int start(gnb_worker_t *gnb_worker){ primary_worker_ctx_t *primary_worker_ctx = gnb_worker->ctx; gnb_core_t *gnb_core = primary_worker_ctx->gnb_core; int i; struct sockaddr_in6 sockaddr6; struct sockaddr_in sockaddr; socklen_t sockaddr_len; if ( gnb_core->conf->udp_socket_type & GNB_ADDR_TYPE_IPV6 ) { for ( i=0; i < gnb_core->conf->udp6_socket_num; i++ ) { gnb_core->udp_ipv6_sockets[i] = socket(AF_INET6, SOCK_DGRAM, 0); gnb_bind_udp_socket_ipv6(gnb_core->udp_ipv6_sockets[i], gnb_core->conf->listen_address6_string, gnb_core->conf->udp6_ports[i]); sockaddr_len = sizeof(struct sockaddr_in6); getsockname( gnb_core->udp_ipv6_sockets[i], (struct sockaddr *)&sockaddr6, &sockaddr_len ); gnb_core->conf->udp6_ports[i] = ntohs(sockaddr6.sin6_port); GNB_LOG1(gnb_core->log,GNB_LOG_ID_MAIN_WORKER, "bind addr6 [%s:%d]\n", gnb_core->conf->listen_address6_string, gnb_core->conf->udp6_ports[i]); } } if ( gnb_core->conf->udp_socket_type & GNB_ADDR_TYPE_IPV4 ) { for ( i=0; i < gnb_core->conf->udp4_socket_num; i++ ) { gnb_core->udp_ipv4_sockets[i] = socket(AF_INET, SOCK_DGRAM, 0); gnb_bind_udp_socket_ipv4(gnb_core->udp_ipv4_sockets[i], gnb_core->conf->listen_address4_string, gnb_core->conf->udp4_ports[i]); if ( 0==gnb_core->conf->udp4_ports[i] ) { sockaddr_len = sizeof(struct sockaddr_in); getsockname( gnb_core->udp_ipv4_sockets[i], (struct sockaddr *)&sockaddr, &sockaddr_len ); gnb_core->conf->udp4_ports[i] = ntohs(sockaddr.sin_port); } gnb_core->conf->udp4_ext_ports[i] = gnb_core->conf->udp4_ports[i]; GNB_LOG1(gnb_core->log,GNB_LOG_ID_MAIN_WORKER, "bind addr4[%s:%d]\n", gnb_core->conf->listen_address4_string, gnb_core->conf->udp4_ports[i]); } } #ifdef __UNIX_LIKE_OS__ //尝试绑定网卡 bind_socket_if(gnb_core); pthread_create(&primary_worker_ctx->tun_udp_loop_thread, NULL, tun_udp_loop_thread_func, gnb_worker); pthread_detach(primary_worker_ctx->tun_udp_loop_thread); #endif #ifdef _WIN32 pthread_create(&primary_worker_ctx->udp_loop_thread, NULL, udp_loop_thread_func, gnb_worker); pthread_detach(primary_worker_ctx->udp_loop_thread); if ( !gnb_core->conf->activate_tun ) { return 0; } pthread_create(&primary_worker_ctx->tun_loop_thread, NULL, tun_loop_thread_func, gnb_worker); pthread_detach(primary_worker_ctx->tun_loop_thread); /*在Windows下如果执行 pthread_detach, pthread_kill 会返回 ESRCH * 事实上,在Windows下执行pthread_kill没发现可以发送信号到线程 */ #endif return 0; } static int stop(gnb_worker_t *gnb_worker){ primary_worker_ctx_t *primary_worker_ctx = gnb_worker->ctx; return 0; } static int notify(gnb_worker_t *gnb_worker){ int ret; primary_worker_ctx_t *primary_worker_ctx = gnb_worker->ctx; #ifdef __UNIX_LIKE_OS__ ret = pthread_kill(primary_worker_ctx->tun_udp_loop_thread,SIGALRM); #endif #ifdef _WIN32 ret = pthread_kill(primary_worker_ctx->udp_loop_thread,SIGHUP); #endif return 0; } gnb_worker_t gnb_primary_worker_mod = { .name = "gnb_primary_worker", .init = init, .release = release, .start = start, .stop = stop, .notify = notify, .ctx = NULL }; opengnb-ver1.6.0.a/src/gnb_ring_buffer_fixed.c000077500000000000000000000065201500454252100213360ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 #include #include "gnb_ring_buffer_fixed.h" size_t gnb_ring_buffer_fixed_sum_size(size_t block_size, unsigned short block_num_mask){ size_t memory_size; size_t block_num = 0xFF+1; switch (block_num_mask) { case 0xFFFF : //65535 case 0x7FFF : //32767 case 0x3FFF : //16383 case 0x1FFF : //8191 case 0xFFF : //4095 case 0x7FF : //2047 case 0x3FF : //1023 case 0x1FF : //511 case 0xFF : //255 case 0x7F : //127 case 0x3F : //63 case 0x1F : //31 case 0xF : //15 case 0x7 : //7 case 0x3 : //3 block_num = block_num_mask+1; break; default: block_num = 0xFF+1; break; } memory_size = sizeof(gnb_ring_buffer_fixed_t) + block_size * block_num; return memory_size; } gnb_ring_buffer_fixed_t* gnb_ring_buffer_fixed_init(void *memory, size_t block_size, unsigned short block_num_mask){ gnb_ring_buffer_fixed_t *gnb_ring_buffer_fixed; size_t memory_size; gnb_ring_buffer_fixed = (gnb_ring_buffer_fixed_t*)memory; memory_size = gnb_ring_buffer_fixed_sum_size(block_size, block_num_mask); memset(memory, 0, memory_size); gnb_ring_buffer_fixed->block_num_mask = block_num_mask; gnb_ring_buffer_fixed->block_size = block_size; gnb_ring_buffer_fixed->memory_size = memory_size; return gnb_ring_buffer_fixed; } void* gnb_ring_buffer_fixed_push(gnb_ring_buffer_fixed_t *ring_buffer_fixed){ int tail_next_idx = (ring_buffer_fixed->tail_idx + 1) & ring_buffer_fixed->block_num_mask; if ( tail_next_idx == ring_buffer_fixed->head_idx ) { return NULL; } void *buffer_header = ring_buffer_fixed->blocks + ring_buffer_fixed->block_size * ring_buffer_fixed->tail_idx; return buffer_header; } void gnb_ring_buffer_fixed_push_submit(gnb_ring_buffer_fixed_t *ring_buffer_fixed){ int tail_next_idx = (ring_buffer_fixed->tail_idx + 1) & ring_buffer_fixed->block_num_mask; ring_buffer_fixed->tail_idx = tail_next_idx; } void* gnb_ring_buffer_fixed_pop(gnb_ring_buffer_fixed_t *ring_buffer_fixed){ if ( ring_buffer_fixed->head_idx == ring_buffer_fixed->tail_idx ) { return NULL; } void *buffer_header = ring_buffer_fixed->blocks + ring_buffer_fixed->block_size * ring_buffer_fixed->head_idx; return buffer_header; } void gnb_ring_buffer_fixed_pop_submit(gnb_ring_buffer_fixed_t *ring_buffer_fixed){ int head_next_idx = (ring_buffer_fixed->head_idx + 1) & ring_buffer_fixed->block_num_mask; ring_buffer_fixed->head_idx = head_next_idx; } opengnb-ver1.6.0.a/src/gnb_ring_buffer_fixed.h000077500000000000000000000034611500454252100213440ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 . */ #ifndef gnb_ring_buffer_fixed_h #define gnb_ring_buffer_fixed_h #include typedef struct _gnb_ring_buffer_fixed_t{ unsigned short block_num_mask; size_t block_size; size_t memory_size; unsigned int head_idx; unsigned int tail_idx; unsigned char blocks[0]; } __attribute__ ((aligned (4))) gnb_ring_buffer_fixed_t; /* block_num_mask must be: 0xFFFF 65535 0x7FFF 32767 0x3FFF 16383 0x1FFF 8191 0xFFF 4095 0x7FF 2047 0x3FF 1023 0x1FF 511 0xFF 255 0x7F 127 0x3F 63 0x1F 31 0xF 15 0x7 7 0x3 3 */ size_t gnb_ring_buffer_fixed_sum_size(size_t block_size, unsigned short block_num_mask); gnb_ring_buffer_fixed_t* gnb_ring_buffer_fixed_init(void *memory, size_t block_size, unsigned short block_num_mask); void* gnb_ring_buffer_fixed_push(gnb_ring_buffer_fixed_t *ring_buffer_fixed); void gnb_ring_buffer_fixed_push_submit(gnb_ring_buffer_fixed_t *ring_buffer_fixed); void* gnb_ring_buffer_fixed_pop(gnb_ring_buffer_fixed_t *ring_buffer_fixed); void gnb_ring_buffer_fixed_pop_submit(gnb_ring_buffer_fixed_t *ring_buffer_fixed); #endif opengnb-ver1.6.0.a/src/gnb_secure_index_service_worker.c000077500000000000000000000663371500454252100234710ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 #include #ifdef _WIN32 #define _POSIX #define __USE_MINGW_ALARM #endif #include #include #include #include #include #include #include #include "gnb.h" #include "gnb_node.h" #include "gnb_worker.h" #include "gnb_ring_buffer_fixed.h" #include "gnb_lru32.h" #include "gnb_time.h" #include "gnb_binary.h" #include "gnb_worker_queue_data.h" #include "ed25519/ed25519.h" #include "crypto/xor/xor.h" #include "gnb_index_frame_type.h" typedef struct _index_service_worker_ctx_t { gnb_core_t *gnb_core; //注意,lur 中保存的是数据(gnb_key_address_t)拷贝,不是指针 gnb_lru32_t *lru; gnb_payload16_t *index_frame_payload; //unsigned char payload_buffer[1024]; uint64_t now_time_sec; uint64_t now_time_usec; pthread_t thread_worker; }index_service_worker_ctx_t; typedef struct _gnb_key_address_t{ gnb_uuid_t uuid64; // key_node 最后发送 post_addr_frame的时间 uint64_t last_post_addr4_sec; uint64_t last_post_addr6_sec; //key_node 最后发送 request_addr_frame 的时间戳 uint64_t last_send_request_addr_usec; //源节点对自身探测的wan地址 uint8_t wan6_addr[16]; uint16_t wan6_port; uint8_t wan4_addr[4]; uint16_t wan4_port; unsigned char node_random_sequence[NODE_RANDOM_SEQUENCE_SIZE]; unsigned char node_random_sequence_sign[ED25519_SIGN_SIZE]; unsigned char address6_list_block[sizeof(gnb_address_list_t) + sizeof(gnb_address_t)*GNB_KEY_ADDRESS_NUM]; unsigned char address4_list_block[sizeof(gnb_address_list_t) + sizeof(gnb_address_t)*GNB_KEY_ADDRESS_NUM]; char attachmenta[INDEX_ATTACHMENT_SIZE]; //保存 PAYLOAD_SUB_TYPE_POST_ADDR 的 attachment char attachmentb[INDEX_ATTACHMENT_SIZE]; //保存 PAYLOAD_SUB_TYPE_POST_ADDR 的 attachment }gnb_key_address_t; static void send_echo_addr_frame(gnb_worker_t *gnb_index_service_worker, unsigned char *key512, gnb_uuid_t uuid64, gnb_address_t *address); static void send_push_addr_frame(gnb_worker_t *gnb_index_service_worker, unsigned char action, unsigned char attachment, unsigned char *src_key, gnb_key_address_t *src_key_address, unsigned char *dst_key, gnb_key_address_t *dst_key_address); static void handle_post_addr_frame(gnb_core_t *gnb_core, gnb_worker_in_data_t *index_service_worker_in_data); static void handle_request_addr_frame(gnb_core_t *gnb_core, gnb_worker_in_data_t *index_service_worker_in_data); /* verify and decrypto OK */ static void handle_post_addr_frame(gnb_core_t *gnb_core, gnb_worker_in_data_t *index_service_worker_in_data){ index_service_worker_ctx_t *index_service_worker_ctx = gnb_core->index_service_worker->ctx; gnb_key_address_t *key_address; post_addr_frame_t *post_addr_frame = (post_addr_frame_t *)&index_service_worker_in_data->payload_st.data; gnb_sockaddress_t *sockaddress = &index_service_worker_in_data->node_addr_st; gnb_node_t *src_node; gnb_uuid_t src_uuid64; src_uuid64 = gnb_ntohll(post_addr_frame->node_uuid64); src_node = GNB_HASH32_UINT64_GET_PTR(gnb_core->uuid_node_map, src_uuid64); if ( NULL==src_node ) { GNB_LOG3(gnb_core->log, GNB_LOG_ID_INDEX_SERVICE_WORKER, "handle_post_addr_frame error src node not found src=%llu %s\n", src_uuid64, GNB_SOCKETADDRSTR1(sockaddress)); return; } if ( !ed25519_verify(post_addr_frame->src_sign, (const unsigned char *)&post_addr_frame->data, sizeof(struct post_addr_frame_data), src_node->public_key) ) { GNB_LOG3(gnb_core->log, GNB_LOG_ID_INDEX_SERVICE_WORKER, "handle_post_addr_frame error invalid signature src=%llu %s\n", src_uuid64, GNB_SOCKETADDRSTR1(sockaddress)); return; } xor_crypto(src_node->crypto_key, (unsigned char *)&post_addr_frame->data, sizeof(struct post_addr_frame_data)); key_address = GNB_LRU32_HASH_GET_VALUE(index_service_worker_ctx->lru, post_addr_frame->data.src_key512, 64); gnb_address_list_t *address6_list; gnb_address_list_t *address4_list; if ( NULL == key_address ) { key_address = (gnb_key_address_t *)alloca( sizeof(gnb_key_address_t) ); memset(key_address,0,sizeof(gnb_key_address_t)); GNB_LRU32_FIXED_STORE(index_service_worker_ctx->lru, post_addr_frame->data.src_key512, 64, key_address); key_address = GNB_LRU32_HASH_GET_VALUE(index_service_worker_ctx->lru, post_addr_frame->data.src_key512, 64); GNB_LOG4(gnb_core->log, GNB_LOG_ID_INDEX_SERVICE_WORKER, "HANDLE POST STORE src_uuid64[%llu] key[%s]\n", src_uuid64, GNB_HEX1_BYTE128(post_addr_frame->data.src_key512)); address6_list = (gnb_address_list_t *)key_address->address6_list_block; address6_list->size = GNB_KEY_ADDRESS_NUM; address4_list = (gnb_address_list_t *)key_address->address4_list_block; address4_list->size = GNB_KEY_ADDRESS_NUM; } else { address6_list = (gnb_address_list_t *)key_address->address6_list_block; address4_list = (gnb_address_list_t *)key_address->address4_list_block; } key_address->uuid64 = gnb_ntohll(post_addr_frame->data.src_uuid64); gnb_address_t *address = alloca(sizeof(gnb_address_t)); address->ts_sec = index_service_worker_ctx->now_time_sec; if ( AF_INET6 == sockaddress->addr_type ) { if ( index_service_worker_ctx->now_time_sec - key_address->last_post_addr6_sec < GNB_POST_ADDR_LIMIT_SEC ) { GNB_LOG3(gnb_core->log, GNB_LOG_ID_INDEX_SERVICE_WORKER, "HANDLE POST receive addr=%llu now_time_sec=%"PRIu64" last_post_addr6_sec=%"PRIu64" LIMIT\n", key_address->uuid64, index_service_worker_ctx->now_time_sec, key_address->last_post_addr6_sec); key_address->last_post_addr6_sec = index_service_worker_ctx->now_time_sec; return; } key_address->last_post_addr6_sec = index_service_worker_ctx->now_time_sec; gnb_set_address6(address, &sockaddress->addr.in6); gnb_address_list3_fifo(address6_list, address); } if ( AF_INET == sockaddress->addr_type ) { if ( index_service_worker_ctx->now_time_sec - key_address->last_post_addr4_sec < GNB_POST_ADDR_LIMIT_SEC ) { GNB_LOG2(gnb_core->log, GNB_LOG_ID_INDEX_SERVICE_WORKER, "HANDLE POST receive addr=%llu now_time_sec=%"PRIu64" last_post_addr4_sec=%"PRIu64" LIMIT\n", key_address->uuid64, index_service_worker_ctx->now_time_sec, key_address->last_post_addr4_sec); key_address->last_post_addr4_sec = index_service_worker_ctx->now_time_sec; return; } key_address->last_post_addr4_sec = index_service_worker_ctx->now_time_sec; gnb_set_address4(address, &sockaddress->addr.in); gnb_address_list3_fifo(address4_list, address); } if ( 0 != post_addr_frame->data.wan6_port ) { memcpy(key_address->wan6_addr,post_addr_frame->data.wan6_addr,16); key_address->wan6_port = post_addr_frame->data.wan6_port; } if ( 'p' == post_addr_frame->data.arg0 ) { if ( 'a' == post_addr_frame->data.arg1 ) { memcpy(key_address->attachmenta, post_addr_frame->data.attachment, INDEX_ATTACHMENT_SIZE); } else if ( 'b' == post_addr_frame->data.arg1 ) { memcpy(key_address->attachmentb, post_addr_frame->data.attachment, INDEX_ATTACHMENT_SIZE); } } send_echo_addr_frame(gnb_core->index_service_worker, post_addr_frame->data.src_key512, key_address->uuid64, address); GNB_LOG3(gnb_core->log, GNB_LOG_ID_INDEX_SERVICE_WORKER, "HANDLE POST addr [%llu][%s]\n", key_address->uuid64, GNB_SOCKETADDRSTR1(sockaddress)); } /*crypto sign*/ static void send_echo_addr_frame(gnb_worker_t *gnb_index_service_worker, unsigned char *key512, gnb_uuid_t uuid64, gnb_address_t *address){ index_service_worker_ctx_t *index_service_worker_ctx = gnb_index_service_worker->ctx; gnb_core_t *gnb_core = index_service_worker_ctx->gnb_core; gnb_node_t *node; int i; index_service_worker_ctx->index_frame_payload->sub_type = PAYLOAD_SUB_TYPE_ECHO_ADDR; gnb_payload16_set_data_len( index_service_worker_ctx->index_frame_payload, sizeof(echo_addr_frame_t) ); echo_addr_frame_t *echo_addr_frame = (echo_addr_frame_t *)index_service_worker_ctx->index_frame_payload->data; memset(echo_addr_frame, 0, sizeof(echo_addr_frame_t)); memcpy(echo_addr_frame->data.dst_key512, key512, 64); echo_addr_frame->data.dst_uuid64 = gnb_htonll(uuid64); echo_addr_frame->data.src_ts_usec = gnb_htonll(index_service_worker_ctx->now_time_usec); if ( AF_INET6 == address->type ) { echo_addr_frame->data.addr_type = '6'; memcpy(echo_addr_frame->data.addr, address->m_address6, 16); //debug_text snprintf(echo_addr_frame->data.text, 80, "ECHO ADDR [%s:%d][%llu]", GNB_ADDR6STR_PLAINTEXT1(address->m_address6), ntohs(address->port), uuid64); } else if ( AF_INET == address->type ) { echo_addr_frame->data.addr_type = '4'; memcpy(echo_addr_frame->data.addr, address->m_address4, 4); //debug_text snprintf(echo_addr_frame->data.text, 80, "ECHO ADDR [%s:%d][%llu]", GNB_ADDR4STR_PLAINTEXT1(address->m_address4), ntohs(address->port), uuid64 ); } echo_addr_frame->data.port = address->port; node = GNB_HASH32_UINT64_GET_PTR(gnb_core->uuid_node_map, uuid64); if ( NULL == node ) { GNB_LOG3(gnb_core->log, GNB_LOG_ID_NODE_WORKER, "send_echo_addr_frame error node=%llu is miss\n", uuid64); return; } xor_crypto(node->crypto_key, (unsigned char *)&echo_addr_frame->data, sizeof(struct echo_addr_frame_data)); ed25519_sign(echo_addr_frame->src_sign, (const unsigned char *)&echo_addr_frame->data, sizeof(struct echo_addr_frame_data), gnb_core->ed25519_public_key, gnb_core->ed25519_private_key); gnb_send_to_node(gnb_core, node, index_service_worker_ctx->index_frame_payload, GNB_ADDR_TYPE_IPV6|GNB_ADDR_TYPE_IPV4); } /*把 src_key_address里nodeid及ip地址 发到 dst_key_address 对于的nodeid的节点*/ /*crypto and sign*/ static void send_push_addr_frame(gnb_worker_t *gnb_index_service_worker, unsigned char action, unsigned char attachment, unsigned char *src_key, gnb_key_address_t *src_key_address, unsigned char *dst_key, gnb_key_address_t *dst_key_address){ gnb_node_t *dst_node; index_service_worker_ctx_t *index_service_worker_ctx = gnb_index_service_worker->ctx; gnb_core_t *gnb_core = index_service_worker_ctx->gnb_core; dst_node = GNB_HASH32_UINT64_GET_PTR(gnb_core->uuid_node_map, dst_key_address->uuid64); if ( NULL==dst_node ) { GNB_LOG3(gnb_core->log, GNB_LOG_ID_INDEX_SERVICE_WORKER, "SEND PUSH ADDR dst=%llu nodeid not found!\n", dst_key_address->uuid64); return; } index_service_worker_ctx->index_frame_payload->sub_type = PAYLOAD_SUB_TYPE_PUSH_ADDR; gnb_payload16_set_data_len( index_service_worker_ctx->index_frame_payload, sizeof(push_addr_frame_t) ); push_addr_frame_t *push_addr_frame = (push_addr_frame_t *)index_service_worker_ctx->index_frame_payload->data; memset(push_addr_frame, 0, sizeof(push_addr_frame_t)); memcpy(push_addr_frame->data.node_key, src_key, 64); push_addr_frame->data.node_uuid64 = gnb_htonll(src_key_address->uuid64); gnb_address_list_t *address6_list = (gnb_address_list_t *)src_key_address->address6_list_block; gnb_address_list_t *address4_list = (gnb_address_list_t *)src_key_address->address4_list_block; if ( 0 != address6_list->array[0].port && ( index_service_worker_ctx->now_time_sec - address6_list->array[0].ts_sec < GNB_ADDRESS_LIFE_TIME_TS_SEC) ) { memcpy(&push_addr_frame->data.addr6_a, &address6_list->array[0].address, 16); push_addr_frame->data.port6_a = address6_list->array[0].port; } if ( 0 != address6_list->array[1].port && ( index_service_worker_ctx->now_time_sec - address6_list->array[1].ts_sec < GNB_ADDRESS_LIFE_TIME_TS_SEC) ) { memcpy(&push_addr_frame->data.addr6_b, &address6_list->array[1].address, 16); push_addr_frame->data.port6_b = address6_list->array[1].port; } if ( 0 != address6_list->array[2].port && ( index_service_worker_ctx->now_time_sec - address6_list->array[2].ts_sec < GNB_ADDRESS_LIFE_TIME_TS_SEC) ) { memcpy(&push_addr_frame->data.addr6_c, &address6_list->array[2].address, 16); push_addr_frame->data.port6_c = address6_list->array[2].port; } if ( 0 != address4_list->array[0].port && ( index_service_worker_ctx->now_time_sec - address4_list->array[0].ts_sec < GNB_ADDRESS_LIFE_TIME_TS_SEC) ) { memcpy(&push_addr_frame->data.addr4_a, &address4_list->array[0].address, 4); push_addr_frame->data.port4_a = address4_list->array[0].port; } if ( 0 != address4_list->array[1].port && ( index_service_worker_ctx->now_time_sec - address4_list->array[1].ts_sec < GNB_ADDRESS_LIFE_TIME_TS_SEC) ) { memcpy(&push_addr_frame->data.addr4_b, &address4_list->array[1].address, 4); push_addr_frame->data.port4_b = address4_list->array[1].port; } if ( 0 != address4_list->array[2].port && ( index_service_worker_ctx->now_time_sec - address4_list->array[2].ts_sec < GNB_ADDRESS_LIFE_TIME_TS_SEC) ) { memcpy(&push_addr_frame->data.addr4_c, &address4_list->array[2].address, 4); push_addr_frame->data.port4_c = address4_list->array[2].port; } //找一个空闲的位置,把节点自探测的 wan_addr6 写入 if ( 0 == push_addr_frame->data.port6_a ) { memcpy(&push_addr_frame->data.addr6_a, &src_key_address->wan6_addr, 16); push_addr_frame->data.port6_a = src_key_address->wan6_port; goto finish_fill_address; } if ( 0 == push_addr_frame->data.port6_b ) { memcpy(&push_addr_frame->data.addr6_b, &src_key_address->wan6_addr, 16); push_addr_frame->data.port6_b = src_key_address->wan6_port; goto finish_fill_address; } if ( 0 == push_addr_frame->data.port6_c ) { memcpy(&push_addr_frame->data.addr6_c, &src_key_address->wan6_addr, 16); push_addr_frame->data.port6_c = src_key_address->wan6_port; goto finish_fill_address; } finish_fill_address: push_addr_frame->data.arg0 = action; if ( 'a' == attachment ) { memcpy(push_addr_frame->data.attachment, src_key_address->attachmenta, INDEX_ATTACHMENT_SIZE); } else if ( 'b' == attachment ) { memcpy(push_addr_frame->data.attachment, src_key_address->attachmentb, INDEX_ATTACHMENT_SIZE); } //debug_text snprintf(push_addr_frame->data.text, 32, "INDEX PUSH ADDR[%llu]=>[%llu]", src_key_address->uuid64, dst_key_address->uuid64); push_addr_frame->index_node_uuid64 = gnb_htonll(gnb_core->local_node->uuid64); xor_crypto(dst_node->crypto_key, (unsigned char *)&push_addr_frame->data, sizeof(struct push_addr_frame_data)); ed25519_sign(push_addr_frame->src_sign, (const unsigned char *)&push_addr_frame->data, sizeof(struct push_addr_frame_data), gnb_core->ed25519_public_key, gnb_core->ed25519_private_key); gnb_address_list_t *dst_address6_list = (gnb_address_list_t *)dst_key_address->address6_list_block; gnb_address_list_t *dst_address4_list = (gnb_address_list_t *)dst_key_address->address4_list_block; //发给节点所有的活跃地址 gnb_send_available_address_list(gnb_core, dst_address6_list, index_service_worker_ctx->index_frame_payload, index_service_worker_ctx->now_time_sec); gnb_send_available_address_list(gnb_core, dst_address4_list, index_service_worker_ctx->index_frame_payload, index_service_worker_ctx->now_time_sec); GNB_LOG3(gnb_core->log, GNB_LOG_ID_INDEX_SERVICE_WORKER, "SEND PUSH ADDR [%llu]->[%llu]\n", src_key_address->uuid64, dst_key_address->uuid64); } /*verify and decrypto*/ static void handle_request_addr_frame(gnb_core_t *gnb_core, gnb_worker_in_data_t *index_service_worker_in_data){ index_service_worker_ctx_t *index_service_worker_ctx = gnb_core->index_service_worker->ctx; request_addr_frame_t *request_addr_frame = (request_addr_frame_t *)&index_service_worker_in_data->payload_st.data; gnb_uuid_t node_uuid64 = gnb_ntohll(request_addr_frame->node_uuid64); gnb_sockaddress_t *sockaddress = &index_service_worker_in_data->node_addr_st; gnb_key_address_t *l_key_address; gnb_key_address_t *r_key_address; gnb_node_t *src_node; src_node = GNB_HASH32_UINT64_GET_PTR(gnb_core->uuid_node_map, node_uuid64); if ( NULL==src_node ) { GNB_LOG3(gnb_core->log, GNB_LOG_ID_INDEX_SERVICE_WORKER, "handle_request_addr_frame error src node not found src=%llu %s\n", node_uuid64, GNB_SOCKETADDRSTR1(sockaddress)); return; } if ( !ed25519_verify(request_addr_frame->src_sign, (const unsigned char *)&request_addr_frame->data, sizeof(struct request_addr_frame_data), src_node->public_key) ) { GNB_LOG3(gnb_core->log, GNB_LOG_ID_INDEX_SERVICE_WORKER, "handle_request_addr_frame error invalid signature src=%llu %s\n", node_uuid64, GNB_SOCKETADDRSTR1(sockaddress)); return; } xor_crypto(src_node->crypto_key, (unsigned char *)&request_addr_frame->data, sizeof(struct request_addr_frame_data)); gnb_uuid_t src_uuid64 = gnb_ntohll(request_addr_frame->data.src_uuid64); gnb_uuid_t dst_uuid64 = gnb_ntohll(request_addr_frame->data.dst_uuid64); l_key_address = GNB_LRU32_HASH_GET_VALUE(index_service_worker_ctx->lru, request_addr_frame->data.src_key512, 64); if ( NULL==l_key_address ) { GNB_LOG3(gnb_core->log, GNB_LOG_ID_INDEX_SERVICE_WORKER, "HANDLE REQUEST src[%llu] => [%llu] l_key_address[%s] is Not Found\n", src_uuid64, dst_uuid64, GNB_HEX1_BYTE128(request_addr_frame->data.src_key512)); return; } if ( (index_service_worker_ctx->now_time_sec - l_key_address->last_post_addr6_sec) < GNB_POST_ADDR_INTERVAL_TIME_SEC*2 || (index_service_worker_ctx->now_time_sec - l_key_address->last_post_addr4_sec) < GNB_POST_ADDR_INTERVAL_TIME_SEC*2 ) { // l_key_address 里面的地址未超时,将其移到双向链表的首部 GNB_LRU32_MOVETOHEAD(index_service_worker_ctx->lru, request_addr_frame->data.src_key512, 64); } else { GNB_LOG3(gnb_core->log, GNB_LOG_ID_INDEX_SERVICE_WORKER, "HANDLE REQUEST src[%llu] => [%llu] l_key_address[%s] time out now[%"PRIu64"] lastpost6[%"PRIu64"] lastpost4[%"PRIu64"]\n", src_uuid64, dst_uuid64, GNB_HEX1_BYTE128(request_addr_frame->data.src_key512), index_service_worker_ctx->now_time_sec, l_key_address->last_post_addr6_sec, l_key_address->last_post_addr4_sec); return; } //一个节点确实可能需要请求很多节点的信息,没设计好之前暂时不做限制 #if 0 if ( (l_key_address->last_send_request_addr_usec - index_service_worker_ctx->now_time_usec) < GNB_REQUEST_ADDR_LIMIT_USEC ) { return; } #endif l_key_address->last_send_request_addr_usec = index_service_worker_ctx->now_time_usec; r_key_address = GNB_LRU32_HASH_GET_VALUE(index_service_worker_ctx->lru, request_addr_frame->data.dst_key512, 64); if ( NULL==r_key_address ) { GNB_LOG3(gnb_core->log, GNB_LOG_ID_INDEX_SERVICE_WORKER, "HANDLE REQUEST src[%llu] => [%llu] r_key_address[%s] is Not Found\n", src_uuid64, dst_uuid64, GNB_HEX1_BYTE128(request_addr_frame->data.dst_key512)); return; } if ( (index_service_worker_ctx->now_time_sec - r_key_address->last_post_addr6_sec) < GNB_POST_ADDR_INTERVAL_TIME_SEC*2 || (index_service_worker_ctx->now_time_sec - r_key_address->last_post_addr4_sec) < GNB_POST_ADDR_INTERVAL_TIME_SEC*2 ) { // r_key_address 里面的地址未超时,将其移到双向链表的首部 GNB_LRU32_MOVETOHEAD(index_service_worker_ctx->lru, request_addr_frame->data.dst_key512, 64); } else { GNB_LOG3(gnb_core->log, GNB_LOG_ID_INDEX_SERVICE_WORKER, "HANDLE REQUEST src[%llu] => [%llu] r_key_address[%s] time out now[%"PRIu64"] lastpost6[%"PRIu64"] lastpost4[%"PRIu64"]\n", src_uuid64, dst_uuid64, GNB_HEX1_BYTE128(request_addr_frame->data.dst_key512), index_service_worker_ctx->now_time_sec, r_key_address->last_post_addr6_sec, r_key_address->last_post_addr4_sec); return; } unsigned char attachment = 'a'; if ( 'g' == request_addr_frame->data.arg0 ) { if ( 'a' == request_addr_frame->data.arg1 ) { attachment = 'a'; } else if( 'b' == request_addr_frame->data.arg1 ) { attachment = 'b'; } } //即使节点开启了多个 socket ,index server 只存最近一份地址 gnb_address_list_t *address6_list = (gnb_address_list_t *)l_key_address->address6_list_block; gnb_address_list_t *address4_list = (gnb_address_list_t *)l_key_address->address4_list_block; gnb_address_t *address = alloca(sizeof(gnb_address_t)); address->ts_sec = index_service_worker_ctx->now_time_sec; if ( AF_INET6 == sockaddress->addr_type ) { gnb_set_address6(address, &sockaddress->addr.in6); gnb_address_list3_fifo(address6_list, address); } if ( AF_INET == sockaddress->addr_type ) { gnb_set_address4(address, &sockaddress->addr.in); gnb_address_list3_fifo(address4_list, address); } send_push_addr_frame(gnb_core->index_service_worker, PUSH_ADDR_ACTION_CONNECT, attachment, request_addr_frame->data.src_key512, l_key_address, request_addr_frame->data.dst_key512, r_key_address); send_push_addr_frame(gnb_core->index_service_worker, PUSH_ADDR_ACTION_CONNECT, attachment, request_addr_frame->data.dst_key512, r_key_address, request_addr_frame->data.src_key512, l_key_address); GNB_LOG3(gnb_core->log, GNB_LOG_ID_INDEX_SERVICE_WORKER, "HANDLE REQUEST push addr src[%llu] => [%llu] r_key_address[%s] now[%"PRIu64"] lastpost6[%"PRIu64"] lastpost4[%"PRIu64"]\n", src_uuid64, dst_uuid64, GNB_HEX1_BYTE128(request_addr_frame->data.dst_key512), index_service_worker_ctx->now_time_sec, r_key_address->last_post_addr6_sec, r_key_address->last_post_addr4_sec); } static void handle_index_frame(gnb_core_t *gnb_core, gnb_worker_in_data_t *index_service_worker_in_data){ gnb_payload16_t *payload = &index_service_worker_in_data->payload_st; if ( GNB_PAYLOAD_TYPE_INDEX != payload->type ) { GNB_LOG3(gnb_core->log, GNB_LOG_ID_INDEX_SERVICE_WORKER, "handle_index_frame GNB_PAYLOAD_TYPE_INDEX != payload->type[%x]\n", payload->type); return; } switch( payload->sub_type ) { case PAYLOAD_SUB_TYPE_POST_ADDR: handle_post_addr_frame(gnb_core, index_service_worker_in_data); break; case PAYLOAD_SUB_TYPE_REQUEST_ADDR: handle_request_addr_frame(gnb_core, index_service_worker_in_data); break; default: break; } return; } static void handle_recv_queue(gnb_core_t *gnb_core){ int i; index_service_worker_ctx_t *index_service_worker_ctx = gnb_core->index_service_worker->ctx; gnb_worker_queue_data_t *receive_queue_data; int ret; for ( i=0; i<1024; i++ ) { receive_queue_data = (gnb_worker_queue_data_t *)gnb_ring_buffer_fixed_pop(gnb_core->index_service_worker->ring_buffer_in); if ( NULL==receive_queue_data ) { break; } handle_index_frame(gnb_core, &receive_queue_data->data.node_in); gnb_ring_buffer_fixed_pop_submit(gnb_core->index_service_worker->ring_buffer_in); } } static void* thread_worker_func( void *data ) { int ret; gnb_worker_t *gnb_index_service_worker = (gnb_worker_t *)data; index_service_worker_ctx_t *index_service_worker_ctx = gnb_index_service_worker->ctx; gnb_core_t *gnb_core = index_service_worker_ctx->gnb_core; gnb_index_service_worker->thread_worker_flag = 1; gnb_index_service_worker->thread_worker_run_flag = 1; gnb_worker_wait_primary_worker_started(gnb_core); GNB_LOG1(gnb_core->log, GNB_LOG_ID_INDEX_SERVICE_WORKER, "start %s success!\n", gnb_index_service_worker->name); do{ gnb_worker_sync_time(&index_service_worker_ctx->now_time_sec, &index_service_worker_ctx->now_time_usec); handle_recv_queue(gnb_core); GNB_SLEEP_MILLISECOND(150); }while(gnb_index_service_worker->thread_worker_flag); return NULL; } static void init(gnb_worker_t *gnb_worker, void *ctx){ gnb_core_t *gnb_core = (gnb_core_t *)ctx; void *memory; size_t memory_size; index_service_worker_ctx_t *index_service_worker_ctx = (index_service_worker_ctx_t *)gnb_heap_alloc(gnb_core->heap, sizeof(index_service_worker_ctx_t)); memset(index_service_worker_ctx, 0, sizeof(index_service_worker_ctx_t)); index_service_worker_ctx->gnb_core = gnb_core; index_service_worker_ctx->index_frame_payload = (gnb_payload16_t *)gnb_heap_alloc(gnb_core->heap, gnb_core->conf->payload_block_size); index_service_worker_ctx->index_frame_payload->type = GNB_PAYLOAD_TYPE_INDEX; index_service_worker_ctx->lru = gnb_lru32_create(gnb_core->heap, gnb_core->conf->index_service_lru_size, sizeof(gnb_key_address_t)); memory_size = gnb_ring_buffer_fixed_sum_size(GNB_INDEX_SERVICE_WORKER_QUEUE_BLOCK_SIZE, gnb_core->conf->index_service_woker_queue_length); memory = gnb_heap_alloc(gnb_core->heap, memory_size); gnb_worker->ring_buffer_in = gnb_ring_buffer_fixed_init(memory, GNB_INDEX_SERVICE_WORKER_QUEUE_BLOCK_SIZE, gnb_core->conf->index_service_woker_queue_length); gnb_worker->ring_buffer_out = NULL; gnb_worker->ctx = index_service_worker_ctx; GNB_LOG1(gnb_core->log, GNB_LOG_ID_INDEX_SERVICE_WORKER, "%s in ring buffer size = %d\n", gnb_worker->name, gnb_core->conf->index_service_woker_queue_length); GNB_LOG1(gnb_core->log, GNB_LOG_ID_INDEX_SERVICE_WORKER, "%s init finish\n", gnb_worker->name); } static void release(gnb_worker_t *gnb_worker){ index_service_worker_ctx_t *index_service_worker_ctx = (index_service_worker_ctx_t *)gnb_worker->ctx; } static int start(gnb_worker_t *gnb_worker){ index_service_worker_ctx_t *index_service_worker_ctx = gnb_worker->ctx; pthread_create(&index_service_worker_ctx->thread_worker, NULL, thread_worker_func, gnb_worker); pthread_detach(index_service_worker_ctx->thread_worker); return 0; } static int stop(gnb_worker_t *gnb_worker){ index_service_worker_ctx_t *index_service_worker_ctx = gnb_worker->ctx; gnb_core_t *gnb_core = index_service_worker_ctx->gnb_core; gnb_worker_t *index_service_worker = gnb_core->index_service_worker; index_service_worker->thread_worker_flag = 0; return 0; } static int notify(gnb_worker_t *gnb_worker){ int ret; index_service_worker_ctx_t *index_service_worker_ctx = gnb_worker->ctx; ret = pthread_kill(index_service_worker_ctx->thread_worker,SIGALRM); return 0; } gnb_worker_t gnb_secure_index_service_worker_mod = { .name = "gnb_secure_index_service_worker", .init = init, .release = release, .start = start, .stop = stop, .notify = notify, .ctx = NULL }; opengnb-ver1.6.0.a/src/gnb_secure_index_worker.c000077500000000000000000001123271500454252100217400ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 #include #ifdef _WIN32 #define _POSIX #define __USE_MINGW_ALARM #endif #include #include #include #include #include #include #include #include "gnb.h" #include "gnb_node.h" #include "gnb_worker.h" #include "gnb_ring_buffer_fixed.h" #include "gnb_time.h" #include "gnb_binary.h" #include "gnb_worker_queue_data.h" #include "gnb_index_frame_type.h" #include "ed25519/ed25519.h" #include "crypto/xor/xor.h" typedef struct _index_worker_ctx_t { gnb_core_t *gnb_core; gnb_payload16_t *index_frame_payload; unsigned char payload_buffer[4096]; struct timeval now_timeval; uint64_t now_time_sec; uint64_t now_time_usec; uint64_t last_post_addr_ts_sec; pthread_t thread_worker; }index_worker_ctx_t; /*crypto and sign*/ static void send_post_addr_frame(gnb_worker_t *gnb_index_worker){ index_worker_ctx_t *index_worker_ctx = gnb_index_worker->ctx; int i; gnb_core_t *gnb_core = index_worker_ctx->gnb_core; index_worker_ctx->index_frame_payload->sub_type = PAYLOAD_SUB_TYPE_POST_ADDR; gnb_payload16_set_data_len( index_worker_ctx->index_frame_payload, sizeof(post_addr_frame_t) ); post_addr_frame_t *post_addr_frame = (post_addr_frame_t *)index_worker_ctx->index_frame_payload->data; memset(post_addr_frame, 0, sizeof(post_addr_frame_t)); post_addr_frame->data.arg0 = 'p'; post_addr_frame->data.arg1 = 'a'; memcpy(post_addr_frame->data.src_key512, gnb_core->local_node->key512, 64); post_addr_frame->data.src_uuid64 = gnb_htonll(gnb_core->local_node->uuid64); post_addr_frame->data.src_ts_usec = gnb_htonll(index_worker_ctx->now_time_usec); if ( 0 != gnb_core->ctl_block->core_zone->wan6_port ) { memcpy(post_addr_frame->data.wan6_addr, gnb_core->ctl_block->core_zone->wan6_addr, 16); post_addr_frame->data.wan6_port = gnb_core->ctl_block->core_zone->wan6_port; GNB_LOG3(gnb_core->log, GNB_LOG_ID_INDEX_WORKER, "post wan6 address [%s:%d]\n", GNB_ADDR6STR1(post_addr_frame->data.wan6_addr), ntohs(post_addr_frame->data.wan6_port)); } //debug_text snprintf(post_addr_frame->data.text,32,"[%llu]POST ADDR",gnb_core->local_node->uuid64); post_addr_frame->node_uuid64 = post_addr_frame->data.src_uuid64; memcpy(index_worker_ctx->payload_buffer, (const unsigned char *)&post_addr_frame->data, sizeof(struct post_addr_frame_data)); for ( i=0; iindex_node_ring.num; i++ ) { printf( "SSSSSSS node=%llu [%s]\n", gnb_core->index_node_ring.nodes[i]->uuid64, GNB_HEX1_BYTE32(gnb_core->index_node_ring.nodes[i]->crypto_key)); xor_crypto_copy(gnb_core->index_node_ring.nodes[i]->crypto_key, (unsigned char *)&post_addr_frame->data, index_worker_ctx->payload_buffer, sizeof(struct post_addr_frame_data)); ed25519_sign(post_addr_frame->src_sign, (const unsigned char *)&post_addr_frame->data, sizeof(struct post_addr_frame_data), gnb_core->ed25519_public_key, gnb_core->ed25519_private_key); gnb_send_to_node(gnb_core, gnb_core->index_node_ring.nodes[i], index_worker_ctx->index_frame_payload, GNB_ADDR_TYPE_IPV6|GNB_ADDR_TYPE_IPV4); } index_worker_ctx->last_post_addr_ts_sec = index_worker_ctx->now_time_sec; for ( i=0; iindex_address_ring.address_list->num; i++ ) { GNB_LOG3(gnb_core->log, GNB_LOG_ID_INDEX_WORKER, "post local address to index %s\n", gnb_get_ip_port_string(&gnb_core->index_address_ring.address_list->array[i], gnb_static_ip_port_string_buffer1, gnb_addr_secure) ); } } /*crypto and sign*/ static void send_request_addr_frame(gnb_worker_t *gnb_index_worker, gnb_node_t *node){ index_worker_ctx_t *index_worker_ctx = gnb_index_worker->ctx; gnb_address_t *address; gnb_node_t* index_node; gnb_core_t *gnb_core = index_worker_ctx->gnb_core; int i; if ( 0 == gnb_core->index_address_ring.address_list->num ) { return; } index_worker_ctx->index_frame_payload->sub_type = PAYLOAD_SUB_TYPE_REQUEST_ADDR; gnb_payload16_set_data_len( index_worker_ctx->index_frame_payload, sizeof(request_addr_frame_t) ); request_addr_frame_t *request_addr_frame = (request_addr_frame_t *)index_worker_ctx->index_frame_payload->data; memset(request_addr_frame, 0, sizeof(request_addr_frame_t)); //请求获取 附件 a request_addr_frame->data.arg0 = 'g'; request_addr_frame->data.arg1 = 'a'; memcpy(request_addr_frame->data.src_key512, gnb_core->local_node->key512, 64); memcpy(request_addr_frame->data.dst_key512, node->key512, 64); request_addr_frame->data.src_uuid64 = gnb_htonll(gnb_core->local_node->uuid64); request_addr_frame->data.dst_uuid64 = gnb_htonll(node->uuid64); request_addr_frame->data.src_ts_usec = gnb_htonll(index_worker_ctx->now_time_usec); //debug_text snprintf(request_addr_frame->data.text,32,"%s %llu==>%llu","REQUEST_ADDR", gnb_core->local_node->uuid64, node->uuid64); request_addr_frame->node_uuid64 = request_addr_frame->data.src_uuid64; if ( GNB_MULTI_ADDRESS_TYPE_FULL != gnb_core->conf->multi_index_type ) { index_node = gnb_select_index_nodes(gnb_core); if ( NULL != index_node ) { xor_crypto(index_node->crypto_key, (unsigned char *)&request_addr_frame->data, sizeof(struct request_addr_frame_data)); ed25519_sign(request_addr_frame->src_sign, (const unsigned char *)&request_addr_frame->data, sizeof(struct request_addr_frame_data), gnb_core->ed25519_public_key, gnb_core->ed25519_private_key); gnb_send_to_node(gnb_core, index_node, index_worker_ctx->index_frame_payload, GNB_ADDR_TYPE_IPV6|GNB_ADDR_TYPE_IPV4); } } else { memcpy(index_worker_ctx->payload_buffer, (const unsigned char *)&request_addr_frame->data, sizeof(struct request_addr_frame_data)); for ( i=0; iindex_node_ring.num; i++ ) { xor_crypto_copy(gnb_core->index_node_ring.nodes[i]->crypto_key, (unsigned char *)&request_addr_frame->data, index_worker_ctx->payload_buffer, sizeof(struct request_addr_frame_data)); ed25519_sign(request_addr_frame->src_sign, (const unsigned char *)&request_addr_frame->data, sizeof(struct request_addr_frame_data), gnb_core->ed25519_public_key, gnb_core->ed25519_private_key); gnb_send_to_node(gnb_core, gnb_core->index_node_ring.nodes[i], index_worker_ctx->index_frame_payload, GNB_ADDR_TYPE_IPV6|GNB_ADDR_TYPE_IPV4); } } node->last_request_addr_sec = index_worker_ctx->now_time_sec; GNB_DEBUG5(gnb_core->log, GNB_LOG_ID_INDEX_WORKER, "SEND REQUEST ADDR %llu ==>%u lkey[%s] rkey[%s]\n", gnb_core->local_node->uuid64, node->uuid64, GNB_HEX1_BYTE128(gnb_core->local_node->key512), GNB_HEX2_BYTE128(node->key512)); } /*crypto and sign*/ static void send_detect_addr_frame(gnb_worker_t *gnb_index_worker, gnb_address_t *in_address, gnb_uuid_t dst_uuid64){ if ( 0 == in_address->port ) { return; } gnb_node_t *dst_node; //因为传入的 in_address 要保留原始的内容在其他地方使用,这里拷贝一份 gnb_address_t address_st; memcpy(&address_st,in_address,sizeof(gnb_address_t)); index_worker_ctx_t *index_worker_ctx = gnb_index_worker->ctx; gnb_core_t *gnb_core = index_worker_ctx->gnb_core; index_worker_ctx->index_frame_payload->sub_type = PAYLOAD_SUB_TYPE_DETECT_ADDR; gnb_payload16_set_data_len( index_worker_ctx->index_frame_payload, sizeof(detect_addr_frame_t) ); detect_addr_frame_t *detect_addr_frame = (detect_addr_frame_t *)index_worker_ctx->index_frame_payload->data; memset(detect_addr_frame, 0, sizeof(detect_addr_frame_t)); detect_addr_frame->data.arg0 = 'd'; memcpy(detect_addr_frame->data.src_key512, gnb_core->local_node->key512, 64); detect_addr_frame->data.src_uuid64 = gnb_htonll(gnb_core->local_node->uuid64); detect_addr_frame->data.dst_uuid64 = gnb_htonll(dst_uuid64); detect_addr_frame->data.src_ts_usec = gnb_htonll(index_worker_ctx->now_time_usec); //debug_text snprintf(detect_addr_frame->data.text,32,"[%llu]DETECT_ADDR[%llu]", gnb_core->local_node->uuid64, dst_uuid64); dst_node = GNB_HASH32_UINT64_GET_PTR(gnb_core->uuid_node_map, dst_uuid64); if ( NULL==dst_node ) { GNB_LOG3(gnb_core->log, GNB_LOG_ID_INDEX_WORKER, "SEND DETECT ADDR dst=%llu nodeid not found!\n", dst_uuid64); return; } xor_crypto(dst_node->crypto_key, (unsigned char *)&detect_addr_frame->data, sizeof(struct detect_addr_frame_data)); ed25519_sign(detect_addr_frame->src_sign, (const unsigned char *)&detect_addr_frame->data, sizeof(struct detect_addr_frame_data), gnb_core->ed25519_public_key, gnb_core->ed25519_private_key); detect_addr_frame->node_uuid64 = gnb_htonll(gnb_core->local_node->uuid64); gnb_send_to_address_through_all_sockets(gnb_core, &address_st, index_worker_ctx->index_frame_payload, gnb_core->conf->address_detect_interval_usec); //以下小范围端口探测,只针对ipv4 if ( AF_INET != address_st.type ) { return; } if ( 0==gnb_core->conf->port_detect_range ) { return; } GNB_LOG2(gnb_core->log, GNB_LOG_ID_INDEX_WORKER, "send DETECT %u ==> %llu address %s port range[%d]\n", gnb_core->local_node->uuid64, dst_uuid64 , GNB_IP_PORT_STR1(&address_st),gnb_core->conf->port_detect_range); uint16_t dst_port = ntohs(address_st.port); int i; for ( i=dst_port-1; i>(dst_port-gnb_core->conf->port_detect_range); i-- ) { if ( i<=1024 ) { break; } address_st.port = htons(i); gnb_send_to_address_through_all_sockets(gnb_core, &address_st, index_worker_ctx->index_frame_payload, gnb_core->conf->address_detect_interval_usec); } for ( i=dst_port+1; i<(dst_port+gnb_core->conf->port_detect_range); i++ ) { if ( i>65535 ) { break; } address_st.port = htons(i); gnb_send_to_address_through_all_sockets(gnb_core, &address_st, index_worker_ctx->index_frame_payload, gnb_core->conf->address_detect_interval_usec); } } /*crypto and sign*/ static void send_detect_addr_frame_arg(gnb_worker_t *gnb_index_worker, gnb_address_t *in_address, gnb_uuid_t dst_uuid64, unsigned char agr0){ if ( 0 == in_address->port ) { return; } gnb_node_t *dst_node; //因为传入的 in_address 要保留原始的内容在其他地方使用,这里拷贝一份 gnb_address_t address_st; memcpy(&address_st,in_address,sizeof(gnb_address_t)); index_worker_ctx_t *index_worker_ctx = gnb_index_worker->ctx; gnb_core_t *gnb_core = index_worker_ctx->gnb_core; index_worker_ctx->index_frame_payload->sub_type = PAYLOAD_SUB_TYPE_DETECT_ADDR; gnb_payload16_set_data_len( index_worker_ctx->index_frame_payload, sizeof(detect_addr_frame_t) ); detect_addr_frame_t *detect_addr_frame = (detect_addr_frame_t *)index_worker_ctx->index_frame_payload->data; memset(detect_addr_frame, 0, sizeof(detect_addr_frame_t)); detect_addr_frame->data.arg0 = agr0; memcpy(detect_addr_frame->data.src_key512, gnb_core->local_node->key512, 64); detect_addr_frame->data.src_uuid64 = gnb_htonll(gnb_core->local_node->uuid64); detect_addr_frame->data.dst_uuid64 = gnb_htonll(dst_uuid64); detect_addr_frame->data.src_ts_usec = gnb_htonll(index_worker_ctx->now_time_usec); //debug_text snprintf(detect_addr_frame->data.text,32,"[%llu]DETECT_ADDR[%llu]", gnb_core->local_node->uuid64, dst_uuid64); dst_node = GNB_HASH32_UINT64_GET_PTR(gnb_core->uuid_node_map, dst_uuid64); if ( NULL==dst_node ) { GNB_LOG3(gnb_core->log, GNB_LOG_ID_INDEX_WORKER, "SEND DETECT ADDR dst=%llu nodeid not found!\n", dst_uuid64); return; } xor_crypto(dst_node->crypto_key, (unsigned char *)&detect_addr_frame->data, sizeof(struct detect_addr_frame_data)); ed25519_sign(detect_addr_frame->src_sign, (const unsigned char *)&detect_addr_frame->data, sizeof(struct detect_addr_frame_data), gnb_core->ed25519_public_key, gnb_core->ed25519_private_key); detect_addr_frame->node_uuid64 = gnb_htonll(gnb_core->local_node->uuid64); gnb_send_to_address(gnb_core, &address_st, index_worker_ctx->index_frame_payload); } static void detect_node_addr(gnb_worker_t *gnb_index_worker, gnb_node_t *node){ gnb_address_list_t *static_address_list; gnb_address_list_t *dynamic_address_list; gnb_address_list_t *resolv_address_list; gnb_address_list_t *push_address_list; static_address_list = (gnb_address_list_t *)&node->static_address_block; dynamic_address_list = (gnb_address_list_t *)&node->dynamic_address_block; resolv_address_list = (gnb_address_list_t *)&node->resolv_address_block; push_address_list = (gnb_address_list_t *)&node->push_address_block; int i; for ( i=0; inum; i++ ) { send_detect_addr_frame(gnb_index_worker, &static_address_list->array[i],node->uuid64); } for ( i=0; inum; i++ ) { send_detect_addr_frame(gnb_index_worker, &push_address_list->array[i],node->uuid64); } for ( i=0; inum; i++ ) { send_detect_addr_frame(gnb_index_worker, &dynamic_address_list->array[i],node->uuid64); } for ( i=0; inum; i++ ) { send_detect_addr_frame(gnb_index_worker, &resolv_address_list->array[i],node->uuid64); } node->detect_count++; } /*verify and decrypto*/ static void handle_push_addr_frame(gnb_core_t *gnb_core, gnb_worker_in_data_t *index_worker_in_data){ gnb_address_list_t *push_address_list; gnb_address_list_t *detect_address_list; index_worker_ctx_t *index_worker_ctx = gnb_core->index_worker->ctx; push_addr_frame_t *push_addr_frame = (push_addr_frame_t *)&index_worker_in_data->payload_st.data; gnb_uuid_t nodeid; gnb_node_t *node; gnb_uuid_t index_nodeid; gnb_node_t *index_node; int i; gnb_sockaddress_t *node_addr = &index_worker_in_data->node_addr_st; if ( 0 == push_addr_frame->index_node_uuid64 ) { GNB_LOG2(gnb_core->log,GNB_LOG_ID_INDEX_WORKER, "handle_push_addr_frame error on safe_index index_node_uuid64=0 index src %s\n", GNB_SOCKETADDRSTR1(node_addr)); return; } index_nodeid = gnb_ntohll(push_addr_frame->index_node_uuid64); index_node = GNB_HASH32_UINT64_GET_PTR(gnb_core->uuid_node_map, index_nodeid); if ( NULL==index_node ) { GNB_LOG2(gnb_core->log, GNB_LOG_ID_INDEX_WORKER, "handle_push_addr_frame error index nodeid=%llu not found %s\n", index_nodeid, GNB_SOCKETADDRSTR1(node_addr)); } if ( !ed25519_verify(push_addr_frame->src_sign, (void *)&push_addr_frame->data, sizeof(struct push_addr_frame_data), index_node->public_key) ) { GNB_LOG2(gnb_core->log, GNB_LOG_ID_INDEX_WORKER, "handle_push_addr_frame error invalid signature index nodeid=%llu %s\n", index_nodeid, GNB_SOCKETADDRSTR1(node_addr)); return; } xor_crypto(index_node->crypto_key, (unsigned char *)&push_addr_frame->data, sizeof(struct push_addr_frame_data)); nodeid = gnb_ntohll(push_addr_frame->data.node_uuid64); node = GNB_HASH32_UINT64_GET_PTR(gnb_core->uuid_node_map, nodeid); if ( NULL == node ) { GNB_LOG2(gnb_core->log, GNB_LOG_ID_INDEX_WORKER, "handle_push_addr_frame error nodeid=%llu not found %s\n", nodeid, GNB_SOCKETADDRSTR1(node_addr)); return; } if ( gnb_core->local_node->uuid64 == node->uuid64 ) { GNB_LOG2(gnb_core->log, GNB_LOG_ID_INDEX_WORKER, "handle_push_addr_frame error nodeid=%llu is local %s\n", nodeid, GNB_SOCKETADDRSTR1(node_addr)); return; } //本地节点如果有 GNB_NODE_TYPE_SLIENCE 属性 将只响应 带有 GNB_NODE_TYPE_FWD 属性的节点 if ( (gnb_core->local_node->type & GNB_NODE_TYPE_SLIENCE) && !(node->type & GNB_NODE_TYPE_FWD) ) { GNB_LOG2(gnb_core->log, GNB_LOG_ID_INDEX_WORKER, "handle_push_addr_frame error local node is slience, src nodeid=%llu %s\n", nodeid, GNB_SOCKETADDRSTR1(node_addr)); return; } if ( node->type & GNB_NODE_TYPE_SLIENCE ) { GNB_LOG2(gnb_core->log, GNB_LOG_ID_INDEX_WORKER, "handle_push_addr_frame error src nodeid=%llu is slience %s\n", nodeid, GNB_SOCKETADDRSTR1(node_addr)); return; } push_address_list = (gnb_address_list_t *)&node->push_address_block; detect_address_list = (gnb_address_list_t *)&node->detect_address4_block; //校验 本地存储的 key512 与 push_addr_frame->data.node_key 是否相同 if ( memcmp(node->key512, push_addr_frame->data.node_key, 64) ) { GNB_LOG2(gnb_core->log,GNB_LOG_ID_INDEX_WORKER, "handle push_addr frame node key not match node[%s] frame[%s]\n", GNB_HEX1_BYTE128(node->key512), GNB_HEX2_BYTE128(push_addr_frame->data.node_key)); return; } gnb_address_list_t *dst_address6_list = alloca( sizeof(gnb_address_list_t) + sizeof(gnb_address_t)*GNB_KEY_ADDRESS_NUM ); memset(dst_address6_list, 0, sizeof(gnb_address_list_t) + sizeof(gnb_address_t)*GNB_KEY_ADDRESS_NUM); dst_address6_list->size = GNB_KEY_ADDRESS_NUM; gnb_address_list_t *dst_address4_list = alloca( sizeof(gnb_address_list_t) + sizeof(gnb_address_t)*GNB_KEY_ADDRESS_NUM ); memset(dst_address4_list, 0, sizeof(gnb_address_list_t) + sizeof(gnb_address_t)*GNB_KEY_ADDRESS_NUM); dst_address4_list->size = GNB_KEY_ADDRESS_NUM; gnb_address_t address_st; memset(&address_st, 0, sizeof(gnb_address_t)); address_st.ts_sec = index_worker_ctx->now_time_sec; address_st.type = AF_INET6; if ( 0 != push_addr_frame->data.port6_a ) { address_st.port = push_addr_frame->data.port6_a; memcpy(&address_st.address.addr6, push_addr_frame->data.addr6_a, 16); gnb_address_list_update(dst_address6_list, &address_st); gnb_address_list_update(push_address_list, &address_st); } if ( 0 != push_addr_frame->data.port6_b ) { address_st.port = push_addr_frame->data.port6_b; memcpy(&address_st.address.addr6, push_addr_frame->data.addr6_b, 16); gnb_address_list_update(dst_address6_list, &address_st); gnb_address_list_update(push_address_list, &address_st); } if ( 0 != push_addr_frame->data.port6_c ) { address_st.port = push_addr_frame->data.port6_c; memcpy(&address_st.address.addr6, push_addr_frame->data.addr6_c, 16); gnb_address_list_update(dst_address6_list, &address_st); gnb_address_list_update(push_address_list, &address_st); } //just for log for ( i=0; inum; i++ ) { GNB_LOG2(gnb_core->log,GNB_LOG_ID_INDEX_WORKER,"RECEIVE_PUSH_ADDR node=%llu %s text='%.*s' action=%c\n", nodeid, GNB_IP_PORT_STR1(&dst_address6_list->array[i]), 32, push_addr_frame->data.text, push_addr_frame->data.arg0); } if ( PUSH_ADDR_ACTION_CONNECT == push_addr_frame->data.arg0 ) { for( i=0; inum; i++ ) { send_detect_addr_frame_arg(gnb_core->index_worker, &dst_address6_list->array[i], nodeid,'d'); } } //下面是处理 ipv4 address_st.type = AF_INET; //由于 detect_address_list 是先进先出,push_addr_frame->data.addr4_a 保存的是最新提交的地址,因此倒序列录入数据,使得最新的地址优先探测 if ( 0 != push_addr_frame->data.port4_c ) { address_st.port = push_addr_frame->data.port4_c; memcpy(&address_st.address.addr4, push_addr_frame->data.addr4_c, 4); gnb_address_list_update(dst_address4_list, &address_st); gnb_address_list_update(push_address_list, &address_st); gnb_address_list3_fifo(detect_address_list, &address_st); } if ( 0 != push_addr_frame->data.port4_b ) { address_st.port = push_addr_frame->data.port4_b; memcpy(&address_st.address.addr4, push_addr_frame->data.addr4_b, 4); gnb_address_list_update(dst_address4_list, &address_st); gnb_address_list_update(push_address_list, &address_st); gnb_address_list3_fifo(detect_address_list, &address_st); } if ( 0 != push_addr_frame->data.port4_a ) { address_st.port = push_addr_frame->data.port4_a; memcpy(&address_st.address.addr4, push_addr_frame->data.addr4_a, 4); gnb_address_list_update(dst_address4_list, &address_st); gnb_address_list_update(push_address_list, &address_st); gnb_address_list3_fifo(detect_address_list, &address_st); } //just for log for ( i=0; inum; i++ ) { GNB_LOG2(gnb_core->log,GNB_LOG_ID_INDEX_WORKER,"RECEIVE_PUSH_ADDR node=%llu %s text='%.*s' action=%c\n", nodeid, GNB_IP_PORT_STR1(&dst_address4_list->array[i]), 32, push_addr_frame->data.text, push_addr_frame->data.arg0); } if ( dst_address6_list->num == 0 && dst_address4_list->num == 0 ) { GNB_LOG2(gnb_core->log,GNB_LOG_ID_INDEX_WORKER,"RECEIVE_PUSH_ADDR ERROR push address incorrect node=%llu text='%.*s' action=%c\n", nodeid, 32, push_addr_frame->data.text, push_addr_frame->data.arg0); return; } node->last_push_addr_sec = index_worker_ctx->now_time_sec; node->detect_count = 0; if ( PUSH_ADDR_ACTION_CONNECT == push_addr_frame->data.arg0 ) { for ( i=0; inum; i++ ) { send_detect_addr_frame(gnb_core->index_worker, &dst_address4_list->array[i], nodeid); } } } static void sync_index_node(gnb_worker_t *gnb_index_worker){ index_worker_ctx_t *index_worker_ctx = gnb_index_worker->ctx; gnb_core_t *gnb_core = index_worker_ctx->gnb_core; gnb_node_t *node; size_t num = gnb_core->ctl_block->node_zone->node_num; if ( 0==num ) { return; } int i; for ( i=0; ictl_block->node_zone->node[i]; if ( gnb_core->local_node->uuid64 == node->uuid64 ) { continue; } if ( node->type & GNB_NODE_TYPE_SLIENCE ) { continue; } //如果本地节点带有 GNB_NODE_TYPE_SLIENCE 属性 将只请求带有 GNB_NODE_TYPE_FWD 属性的节点的地址 if ( (gnb_core->local_node->type & GNB_NODE_TYPE_SLIENCE) && !(node->type & GNB_NODE_TYPE_FWD) ) { continue; } if ( (GNB_NODE_STATUS_IPV6_PONG | GNB_NODE_STATUS_IPV4_PONG) & node->udp_addr_status ) { continue; } //自身的频率限制 if ( (index_worker_ctx->now_time_sec - node->last_request_addr_sec) < GNB_REQUEST_ADDR_INTERVAL_SEC ) { continue; } if ( node->detect_count < GNB_NODE_MAX_DETECT_TIMES ) { detect_node_addr(gnb_index_worker, node); } send_request_addr_frame(gnb_index_worker,node); node->last_request_addr_sec = index_worker_ctx->now_time_sec; } } /*verify and decrypto*/ static void handle_echo_addr_frame(gnb_core_t *gnb_core, gnb_worker_in_data_t *index_worker_in_data){ index_worker_ctx_t *index_worker_ctx = gnb_core->index_worker->ctx; gnb_sockaddress_t *sockaddress = &index_worker_in_data->node_addr_st; echo_addr_frame_t *echo_addr_frame = (echo_addr_frame_t *)&index_worker_in_data->payload_st.data; gnb_uuid_t dst_uuid64; gnb_uuid_t index_nodeid; gnb_node_t *index_node; if ( 0 == echo_addr_frame->index_node_uuid64 ) { GNB_LOG2(gnb_core->log,GNB_LOG_ID_INDEX_WORKER, "handle echo_addr frame on safe_index index_node_uuid64=0 index src %s\n", GNB_SOCKETADDRSTR1(sockaddress)); return; } index_nodeid = gnb_ntohll(echo_addr_frame->index_node_uuid64); index_node = GNB_HASH32_UINT64_GET_PTR(gnb_core->uuid_node_map, index_nodeid); if ( !ed25519_verify(echo_addr_frame->src_sign, (void *)&echo_addr_frame->data, sizeof(struct echo_addr_frame_data), index_node->public_key) ) { GNB_LOG2(gnb_core->log, GNB_LOG_ID_NODE_WORKER, "handle_echo_addr_frame invalid signature index nodeid=%llu %s\n", index_nodeid, GNB_SOCKETADDRSTR1(sockaddress)); return; } xor_crypto(index_node->crypto_key, (unsigned char *)&echo_addr_frame->data, sizeof(struct echo_addr_frame_data)); dst_uuid64 = gnb_ntohll(echo_addr_frame->data.dst_uuid64); if ( dst_uuid64 != gnb_core->local_node->uuid64 ) { return; } gnb_address_t *address = alloca(sizeof(gnb_address_t)); if ( AF_INET6 == sockaddress->addr_type ) { gnb_set_address6(address, &sockaddress->addr.in6); } if ( AF_INET == sockaddress->addr_type ) { gnb_set_address4(address, &sockaddress->addr.in); } /* 如果 index 节点有多个 ipv6 地址,这里得到地址不一定与发送的目的地址相同 */ int idx = gnb_address_list_find(gnb_core->index_address_ring.address_list, address); if ( -1 == idx ) { return; } //更新最后一次在 n 个 index 节点中的其中一个返回echo的时间戳 gnb_core->index_address_ring.address_list->update_sec = index_worker_ctx->now_time_sec; //更新返回 ehco 的index 节点的地址对应的时间戳 gnb_core->index_address_ring.address_list->array[idx].ts_sec = index_worker_ctx->now_time_sec; if ( '6' == echo_addr_frame->data.addr_type ) { memcpy(&gnb_core->local_node->udp_sockaddr6.sin6_addr, &echo_addr_frame->data.addr, 16); gnb_core->local_node->udp_sockaddr6.sin6_port = echo_addr_frame->data.port; GNB_LOG3(gnb_core->log,GNB_LOG_ID_INDEX_WORKER,"get echo address %s:%d from index %s\n", GNB_ADDR6STR1(echo_addr_frame->data.addr), ntohs(echo_addr_frame->data.port), GNB_SOCKETADDRSTR2(sockaddress)); } else if ( '4' == echo_addr_frame->data.addr_type ) { memcpy(&gnb_core->local_node->udp_sockaddr4.sin_addr, &echo_addr_frame->data.addr, 4); gnb_core->local_node->udp_sockaddr4.sin_port = echo_addr_frame->data.port; GNB_LOG3(gnb_core->log,GNB_LOG_ID_INDEX_WORKER,"get echo address %s:%d from index %s\n", GNB_ADDR4STR1(echo_addr_frame->data.addr), ntohs(echo_addr_frame->data.port), GNB_SOCKETADDRSTR2(sockaddress)); } else { GNB_LOG3(gnb_core->log,GNB_LOG_ID_INDEX_WORKER,"handle echo address type error%.*s from %s\n", 80, echo_addr_frame->data.text, GNB_SOCKETADDRSTR2(sockaddress)); return; } } /*verify and decrypto*/ static void handle_detect_addr_frame(gnb_core_t *gnb_core, gnb_worker_in_data_t *index_worker_in_data){ gnb_address_list_t *dynamic_address_list; index_worker_ctx_t *index_worker_ctx = gnb_core->index_worker->ctx; detect_addr_frame_t *detect_addr_frame = (detect_addr_frame_t *)&index_worker_in_data->payload_st.data; gnb_sockaddress_t *sockaddress = &index_worker_in_data->node_addr_st; gnb_uuid_t node_uuid64 = gnb_ntohll(detect_addr_frame->node_uuid64); gnb_node_t *src_node; src_node = GNB_HASH32_UINT64_GET_PTR(gnb_core->uuid_node_map, node_uuid64); if ( NULL==src_node ) { GNB_LOG3(gnb_core->log, GNB_LOG_ID_INDEX_WORKER, "HANDLE DETECT ADDR src=%llu nodeid not found! %s\n", node_uuid64, GNB_SOCKETADDRSTR1(sockaddress)); return; } if ( !ed25519_verify(detect_addr_frame->src_sign, (const unsigned char *)&detect_addr_frame->data, sizeof(struct detect_addr_frame_data), src_node->public_key) ) { GNB_LOG3(gnb_core->log, GNB_LOG_ID_INDEX_WORKER, "111111 handle_detect_addr_frame error invalid signature src=%llu %s\n", node_uuid64, GNB_SOCKETADDRSTR1(sockaddress)); return; } xor_crypto(src_node->crypto_key, (unsigned char *)&detect_addr_frame->data, sizeof(struct detect_addr_frame_data)); gnb_uuid_t src_uuid64 = gnb_ntohll(detect_addr_frame->data.src_uuid64); gnb_uuid_t dst_uuid64 = gnb_ntohll(detect_addr_frame->data.dst_uuid64); if ( src_uuid64 != node_uuid64 ) { GNB_LOG3(gnb_core->log, GNB_LOG_ID_INDEX_WORKER, "handle_detect_addr_frame error invalid src=%llu dst=%llu node_uuid64=%llu %s\n", src_uuid64, dst_uuid64, node_uuid64, GNB_SOCKETADDRSTR1(sockaddress)); return; } if ( src_node->type & GNB_NODE_TYPE_SLIENCE ) { return; } //本地节点如果有 GNB_NODE_TYPE_SLIENCE 属性 将只响应 带有 GNB_NODE_TYPE_FWD 属性的节点 if ( (gnb_core->local_node->type & GNB_NODE_TYPE_SLIENCE) && !(src_node->type & GNB_NODE_TYPE_FWD) ) { return; } dynamic_address_list = (gnb_address_list_t *)&src_node->dynamic_address_block; if ( 0 != memcmp(src_node->key512, detect_addr_frame->data.src_key512, 64) ) { GNB_LOG2(gnb_core->log,GNB_LOG_ID_INDEX_WORKER,"handle detect addr invalid key512 src=%llu %s !!\n", src_uuid64, GNB_SOCKETADDRSTR1(sockaddress)); return; } gnb_address_t *address = alloca(sizeof(gnb_address_t)); memset(address,0,sizeof(gnb_address_t)); address->socket_idx = index_worker_in_data->socket_idx; address->ts_sec = index_worker_ctx->now_time_usec; if ( AF_INET6 == sockaddress->addr_type ) { if ( 0 != gnb_determine_subnet6_prefixlen96(sockaddress->addr.in6.sin6_addr, gnb_core->local_node->tun_ipv6_addr ) ) { GNB_LOG3(gnb_core->log,GNB_LOG_ID_NODE_WORKER, "handle_detect_addr_frame IPV6 Warning src[%llu]->dst[%llu] idx=%u %s\n", src_node->uuid64, dst_uuid64, index_worker_in_data->socket_idx, GNB_ADDR6STR1(&sockaddress->addr.in6.sin6_addr) ); return; } if ( 'e' == detect_addr_frame->data.arg0 ) { src_node->udp_addr_status |= GNB_NODE_STATUS_IPV6_PONG; src_node->addr6_update_ts_sec = index_worker_ctx->now_time_sec; } else { src_node->udp_addr_status |= GNB_NODE_STATUS_IPV6_PING; } //只有发生改变的时候才更新 if ( 0 != gnb_cmp_sockaddr_in6(&src_node->udp_sockaddr6, &sockaddress->addr.in6) || index_worker_in_data->socket_idx != src_node->socket6_idx ) { src_node->udp_sockaddr6 = sockaddress->addr.in6; src_node->socket6_idx = index_worker_in_data->socket_idx; } gnb_set_address6(address, &sockaddress->addr.in6); GNB_LOG2(gnb_core->log, GNB_LOG_ID_INDEX_WORKER, "==###== RECEIVE_DETECT_ADDR6 node[%llu]->[%llu] idx[%u]%s[%c] ==###==\n", src_uuid64, dst_uuid64, src_node->socket6_idx, GNB_IP_PORT_STR1(address), detect_addr_frame->data.arg0); } if ( AF_INET == sockaddress->addr_type ) { if ( 0 != gnb_determine_subnet4(sockaddress->addr.in.sin_addr, gnb_core->local_node->tun_addr4, gnb_core->local_node->tun_netmask_addr4) ) { GNB_LOG3(gnb_core->log,GNB_LOG_ID_NODE_WORKER, "handle_detect_addr_frame IPV4 Warning src[%llu]->dst[%llu] idx=%u %s\n", src_node->uuid64, dst_uuid64, index_worker_in_data->socket_idx, GNB_ADDR4STR1(&sockaddress->addr.in.sin_addr) ); return; } if ( 'e' == detect_addr_frame->data.arg0 ) { src_node->udp_addr_status |= GNB_NODE_STATUS_IPV4_PONG; src_node->addr4_update_ts_sec = index_worker_ctx->now_time_sec; } else { src_node->udp_addr_status |= GNB_NODE_STATUS_IPV4_PING; } //只有发生改变的时候才更新 if ( 0 != gnb_cmp_sockaddr_in(&src_node->udp_sockaddr4, &sockaddress->addr.in) || index_worker_in_data->socket_idx != src_node->socket4_idx ) { src_node->udp_sockaddr4 = sockaddress->addr.in; src_node->socket4_idx = index_worker_in_data->socket_idx; } gnb_set_address4(address, &sockaddress->addr.in); GNB_LOG2(gnb_core->log, GNB_LOG_ID_INDEX_WORKER, "==###== RECEIVE_DETECT_ADDR4 node[%llu]->[%llu] idx[%u]%s[%c] ==###==\n", src_uuid64, dst_uuid64, src_node->socket4_idx, GNB_IP_PORT_STR1(address), detect_addr_frame->data.arg0); } address->ts_sec = index_worker_ctx->now_time_sec; gnb_address_list_update(dynamic_address_list, address); if ( 'e' != detect_addr_frame->data.arg0 ) { send_detect_addr_frame_arg(gnb_core->index_worker, address, src_uuid64, 'e'); GNB_LOG3(gnb_core->log, GNB_LOG_ID_INDEX_WORKER, "ECHO DETECT -> node[%llu] idx[%u]%s\n", src_uuid64, src_node->socket4_idx, GNB_IP_PORT_STR1(address)); } } static void handle_index_frame(gnb_core_t *gnb_core, gnb_worker_in_data_t *index_worker_in_data){ gnb_payload16_t *payload = &index_worker_in_data->payload_st; if ( GNB_PAYLOAD_TYPE_INDEX != payload->type ) { GNB_LOG2(gnb_core->log, GNB_LOG_ID_INDEX_WORKER, "handle_index_frame GNB_PAYLOAD_TYPE_INDEX != payload->type[%x]\n", payload->type); return; } switch ( payload->sub_type ) { case PAYLOAD_SUB_TYPE_ECHO_ADDR: handle_echo_addr_frame(gnb_core, index_worker_in_data); break; case PAYLOAD_SUB_TYPE_PUSH_ADDR: handle_push_addr_frame(gnb_core, index_worker_in_data); break; case PAYLOAD_SUB_TYPE_DETECT_ADDR: handle_detect_addr_frame(gnb_core, index_worker_in_data); break; default: break; } return; } static void handle_recv_queue(gnb_core_t *gnb_core){ int i; index_worker_ctx_t *index_worker_ctx = gnb_core->index_worker->ctx; gnb_worker_queue_data_t *receive_queue_data; int ret; for ( i=0; i<1024; i++ ) { receive_queue_data = (gnb_worker_queue_data_t *)gnb_ring_buffer_fixed_pop( gnb_core->index_worker->ring_buffer_in ); if ( NULL == receive_queue_data ) { break; } handle_index_frame(gnb_core, &receive_queue_data->data.node_in); gnb_ring_buffer_fixed_pop_submit( gnb_core->index_worker->ring_buffer_in ); } } static void* thread_worker_func( void *data ) { int ret; gnb_worker_t *gnb_index_worker = (gnb_worker_t *)data; index_worker_ctx_t *index_worker_ctx = gnb_index_worker->ctx; gnb_core_t *gnb_core = index_worker_ctx->gnb_core; gnb_index_worker->thread_worker_flag = 1; gnb_index_worker->thread_worker_run_flag = 1; gnb_worker_wait_primary_worker_started(gnb_core); GNB_LOG1(gnb_core->log, GNB_LOG_ID_INDEX_WORKER, "start %s success!\n", gnb_index_worker->name); do{ gnb_worker_sync_time(&index_worker_ctx->now_time_sec, &index_worker_ctx->now_time_usec); handle_recv_queue(gnb_core); if ( 0 ==gnb_core->index_address_ring.address_list->num ) { goto next; } if ( (index_worker_ctx->now_time_sec - index_worker_ctx->last_post_addr_ts_sec) > GNB_POST_ADDR_INTERVAL_TIME_SEC ) { send_post_addr_frame(gnb_index_worker); } sync_index_node(gnb_index_worker); next: GNB_SLEEP_MILLISECOND(150); }while(gnb_index_worker->thread_worker_flag); return NULL; } static void init(gnb_worker_t *gnb_worker, void *ctx){ gnb_core_t *gnb_core = (gnb_core_t *)ctx; void *memory; size_t memory_size; index_worker_ctx_t *index_worker_ctx = (index_worker_ctx_t *)gnb_heap_alloc(gnb_core->heap, sizeof(index_worker_ctx_t)); memset(index_worker_ctx, 0, sizeof(index_worker_ctx_t)); index_worker_ctx->index_frame_payload = (gnb_payload16_t *)gnb_heap_alloc(gnb_core->heap, gnb_core->conf->payload_block_size); index_worker_ctx->index_frame_payload->type = GNB_PAYLOAD_TYPE_INDEX; index_worker_ctx->gnb_core = gnb_core; memory_size = gnb_ring_buffer_fixed_sum_size(GNB_INDEX_WORKER_QUEUE_BLOCK_SIZE, gnb_core->conf->index_woker_queue_length); memory = gnb_heap_alloc(gnb_core->heap, memory_size); gnb_worker->ring_buffer_in = gnb_ring_buffer_fixed_init(memory, GNB_INDEX_WORKER_QUEUE_BLOCK_SIZE, gnb_core->conf->index_woker_queue_length); gnb_worker->ring_buffer_out = NULL; gnb_worker->ctx = index_worker_ctx; GNB_LOG1(gnb_core->log, GNB_LOG_ID_INDEX_WORKER, "%s in ring buffer size = %d\n", gnb_worker->name, gnb_core->conf->index_woker_queue_length); GNB_LOG1(gnb_core->log, GNB_LOG_ID_INDEX_WORKER, "%s init finish\n", gnb_worker->name); } static void release(gnb_worker_t *gnb_worker){ index_worker_ctx_t *index_worker_ctx = (index_worker_ctx_t *)gnb_worker->ctx; } static int start(gnb_worker_t *gnb_worker){ index_worker_ctx_t *index_worker_ctx = gnb_worker->ctx; pthread_create(&index_worker_ctx->thread_worker, NULL, thread_worker_func, gnb_worker); pthread_detach(index_worker_ctx->thread_worker); return 0; } static int stop(gnb_worker_t *gnb_worker){ index_worker_ctx_t *index_worker_ctx = gnb_worker->ctx; gnb_core_t *gnb_core = index_worker_ctx->gnb_core; gnb_worker_t *index_worker = gnb_core->index_worker; index_worker->thread_worker_flag = 0; return 0; } static int notify(gnb_worker_t *gnb_worker){ int ret; index_worker_ctx_t *index_worker_ctx = gnb_worker->ctx; ret = pthread_kill(index_worker_ctx->thread_worker,SIGALRM); return 0; } gnb_worker_t gnb_secure_index_worker_mod = { .name = "gnb_secure_index_worker", .init = init, .release = release, .start = start, .stop = stop, .notify = notify, .ctx = NULL }; opengnb-ver1.6.0.a/src/gnb_time.c000077500000000000000000000040711500454252100166240ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 #include #ifdef _WIN32 #include #include #include #define _POSIX_C_SOURCE 1 //使得 localtime_r 等函数有效 #endif #include #include #include "gnb_time.h" uint64_t gnb_timestamp_sec(){ int ret; struct timeval cur_time; uint64_t u64; ret = gettimeofday(&cur_time,NULL); if (0!=ret) { return 0; } u64 = (uint64_t)cur_time.tv_sec; return u64; } uint64_t gnb_timestamp_usec(){ int ret; struct timeval cur_time; uint64_t u64; ret = gettimeofday(&cur_time,NULL); if (0!=ret) { return 0; } u64 = (uint64_t)cur_time.tv_sec*1000000 + cur_time.tv_usec; return u64; } void gnb_now_timef(const char *format, char *buffer, size_t buffer_size){ time_t t; struct tm ltm; time (&t); localtime_r(&t, <m); strftime (buffer,buffer_size,format,<m); } void gnb_timef(const char *format, time_t t, char *buffer, size_t buffer_size){ struct tm ltm; localtime_r(&t, <m); strftime (buffer,buffer_size,format,<m); } int gnb_now_mday(){ time_t t; struct tm ltm; time (&t); localtime_r(&t, <m); return ltm.tm_mday; } int gnb_now_yday(){ time_t t; struct tm ltm; time (&t); localtime_r(&t, <m); return ltm.tm_yday; } opengnb-ver1.6.0.a/src/gnb_time.h000077500000000000000000000027001500454252100166260ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 . */ #ifndef GNB_TIME_H #define GNB_TIME_H #if defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) || defined(__OpenBSD__) #define __UNIX_LIKE_OS__ 1 #endif #include #include #include uint64_t gnb_timestamp_sec(); /*微秒*/ uint64_t gnb_timestamp_usec(); //format:"%Y_%m_%d_%H.%M.%S" void gnb_now_timef(const char *format, char *buffer, size_t buffer_size); void gnb_timef(const char *format, time_t t, char *buffer, size_t buffer_size); /* 获得当前月的当天数字 */ int gnb_now_mday(); int gnb_now_yday(); #define GNB_TIME_STRING_MAX 64 #ifdef __UNIX_LIKE_OS__ #define GNB_SLEEP_MILLISECOND(millisecond) usleep(1000 * millisecond) #endif #if defined(_WIN32) #define GNB_SLEEP_MILLISECOND(millisecond) Sleep(millisecond) #endif #endif opengnb-ver1.6.0.a/src/gnb_tun_drv.h000077500000000000000000000034711500454252100173570ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 . */ #ifndef GNB_TUN_DRV_H #define GNB_TUN_DRV_H typedef struct _gnb_core_t gnb_core_t; typedef int (*init_tun_func_t)(gnb_core_t *gnb_core); typedef int (*open_tun_func_t)(gnb_core_t *gnb_core); typedef int (*read_tun_func_t)(gnb_core_t *gnb_core, void *buf, size_t buf_size); typedef int (*write_tun_func_t)(gnb_core_t *gnb_core, void *buf, size_t buf_size); typedef int (*close_tun_func_t)(gnb_core_t *gnb_core); typedef int (*loop_tun_func_t)(gnb_core_t *gnb_core); typedef int (*release_tun_func_t)(gnb_core_t *gnb_core); typedef struct _gnb_tun_drv_t { init_tun_func_t init_tun; open_tun_func_t open_tun; read_tun_func_t read_tun; write_tun_func_t write_tun; close_tun_func_t close_tun; release_tun_func_t release_tun; }gnb_tun_drv_t; #if defined(__FreeBSD__) extern gnb_tun_drv_t gnb_tun_drv_freebsd; #endif #if defined(__OpenBSD__) extern gnb_tun_drv_t gnb_tun_drv_openbsd; #endif #if defined(__APPLE__) extern gnb_tun_drv_t gnb_tun_drv_darwin; #endif #if defined(__linux__) extern gnb_tun_drv_t gnb_tun_drv_linux; #endif #if defined(_WIN32) extern gnb_tun_drv_t gnb_tun_drv_win32; extern gnb_tun_drv_t gnb_tun_drv_wintun; #endif #endif opengnb-ver1.6.0.a/src/gnb_type.h000077500000000000000000000014771500454252100166630ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 . */ #ifndef GNB_TYPE_H #define GNB_TYPE_H typedef unsigned long long int gnb_uint64_t; /* 64 bits node id*/ typedef unsigned long long int gnb_uuid_t; #endif opengnb-ver1.6.0.a/src/gnb_udp.c000077500000000000000000000046231500454252100164610ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 #include #include #include #if defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) || defined(__OpenBSD__) #include #include #include #endif #ifdef _WIN32 #define _POSIX #undef _WIN32_WINNT #define _WIN32_WINNT 0x0600 #include #include #endif #include "gnb_udp.h" int gnb_bind_udp_socket_ipv4(int socketfd,const char *host, int port) { struct sockaddr_in svr_addr; memset(&svr_addr, 0, sizeof(struct sockaddr_in)); svr_addr.sin_family = AF_INET; svr_addr.sin_port = htons(port); if ( NULL != host ) { svr_addr.sin_addr.s_addr = inet_addr(host); } else { svr_addr.sin_addr.s_addr = htonl(INADDR_ANY); } int on = 1; setsockopt( socketfd, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on) ); if ( bind(socketfd, (struct sockaddr *)&svr_addr, sizeof(struct sockaddr_in)) < 0 ) { perror("bind"); return -1; } return 0; } int gnb_bind_udp_socket_ipv6(int socketfd,const char *host, int port) { struct sockaddr_in6 svr_addr; memset(&svr_addr,0, sizeof(struct sockaddr_in6)); svr_addr.sin6_family = AF_INET6; svr_addr.sin6_port = htons(port); if ( NULL != host ) { inet_pton( AF_INET6, host, &svr_addr.sin6_addr); } else { svr_addr.sin6_addr = in6addr_any; } int on; on = 1; setsockopt(socketfd, SOL_SOCKET, SO_REUSEADDR,(const char *)&on, sizeof(on) ); on = 1; setsockopt(socketfd, IPPROTO_IPV6, IPV6_V6ONLY,(char *)&on, sizeof(on) ); if ( bind(socketfd, (struct sockaddr *)&svr_addr, sizeof(struct sockaddr_in6))<0 ) { perror("bind"); return -1; } return 0; } opengnb-ver1.6.0.a/src/gnb_udp.h000077500000000000000000000015351500454252100164650ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 . */ #ifndef GNB_UDP_H #define GNB_UDP_H int gnb_bind_udp_socket_ipv4(int socketfd,const char *host, int port); int gnb_bind_udp_socket_ipv6(int socketfd,const char *host, int port); #endif opengnb-ver1.6.0.a/src/gnb_uf_node_frame_type.h000077500000000000000000000026261500454252100215310ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 . */ #ifndef GNB_UF_NODE_FRAME_TYPE_H #define GNB_UF_NODE_FRAME_TYPE_H #pragma pack(push, 1) typedef struct _uf_node_notify_frame_t { struct __attribute__((__packed__)) uf_node_notify_frame_data { gnb_uuid_t src_uuid64; //发送方的uuid64 gnb_uuid_t dst_uuid64; //接收方的uuid64 gnb_uuid_t df_uuid64; //direct forwarding node uuid64 int64_t addr6_ping_latency_usec; int64_t addr4_ping_latency_usec; unsigned char attachment[128]; unsigned char text[64]; }data; unsigned char src_sign[ED25519_SIGN_SIZE]; }__attribute__ ((__packed__)) uf_node_notify_frame_t; #define UF_NODE_NOTIFY_FRAME_PAYLOAD_SIZE (sizeof(gnb_payload16_t) + sizeof(uf_node_notify_frame_t)) #pragma pack(pop) #endif opengnb-ver1.6.0.a/src/gnb_unified_forwarding.c000077500000000000000000000360771500454252100215460ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 "gnb.h" #include "gnb_node.h" #include "gnb_hash32.h" #include "gnb_pf.h" #include "gnb_payload16.h" #include "gnb_address.h" #include "gnb_unified_forwarding.h" #include "protocol/network_protocol.h" #pragma pack(push, 1) typedef struct _gnb_unified_forwarding_frame_foot_t { gnb_uuid_t src_nodeid; gnb_uuid_t dst_nodeid; gnb_uuid_t unified_forwarding_nodeid; uint64_t unified_forwarding_seq; } __attribute__ ((__packed__)) gnb_unified_forwarding_frame_foot_t; #pragma pack(pop) void gnb_setup_unified_forwarding_nodeid(gnb_core_t *gnb_core, gnb_node_t *dst_node){ int i; int select_idx = 0; if ( 0 != dst_node->unified_forwarding_nodeid && (gnb_core->now_time_sec - dst_node->unified_forwarding_node_ts_sec) > GNB_UNIFIED_FORWARDING_NODE_EXPIRED_SEC ) { return; } for ( i=1; inow_time_sec - dst_node->unified_forwarding_node_array[i].last_ts_sec) > GNB_UNIFIED_FORWARDING_NODE_ARRAY_EXPIRED_SEC ) { continue; } if ( dst_node->unified_forwarding_node_array[select_idx].last_ts_sec > dst_node->unified_forwarding_node_array[i].last_ts_sec ) { select_idx = i; } } if ( select_idx >= 0 ) { dst_node->unified_forwarding_nodeid = dst_node->unified_forwarding_node_array[select_idx].uuid64; dst_node->unified_forwarding_node_ts_sec = gnb_core->now_time_sec; } } int gnb_unified_forwarding_tun(gnb_core_t *gnb_core, gnb_pf_ctx_t *pf_ctx){ gnb_node_t *dst_node; gnb_payload16_t *payload; uint16_t in_payload_size; gnb_unified_forwarding_frame_foot_t *unified_forwarding_frame_foot; gnb_node_t *unified_forwarding_node; dst_node = pf_ctx->dst_node; payload = pf_ctx->fwd_payload; gnb_setup_unified_forwarding_nodeid(gnb_core, dst_node); if ( 0 == dst_node->unified_forwarding_nodeid ) { GNB_LOG3(gnb_core->log, GNB_LOG_ID_PF, "unified forwarding from tun dst=%llu nodeid not found!\n", dst_node->uuid64); return -1; } unified_forwarding_node = GNB_HASH32_UINT64_GET_PTR(gnb_core->uuid_node_map, dst_node->unified_forwarding_nodeid); if ( NULL == unified_forwarding_node ) { GNB_LOG3(gnb_core->log, GNB_LOG_ID_PF, "Unified Forwarding from tun fwd %llu not found dst=%llu\n", dst_node->unified_forwarding_nodeid, dst_node->uuid64); return -2; } in_payload_size = gnb_payload16_size(payload); unified_forwarding_frame_foot = ( (void *)payload ) + in_payload_size; payload->sub_type = payload->sub_type | GNB_PAYLOAD_SUB_TYPE_IPFRAME_UNIFIED; gnb_payload16_set_size( payload, in_payload_size + sizeof(gnb_unified_forwarding_frame_foot_t) ); unified_forwarding_frame_foot->src_nodeid = gnb_htonll(gnb_core->local_node->uuid64); unified_forwarding_frame_foot->dst_nodeid = gnb_htonll(dst_node->uuid64); unified_forwarding_frame_foot->unified_forwarding_nodeid = gnb_htonll(dst_node->unified_forwarding_nodeid); if ( dst_node->unified_forwarding_send_seq < gnb_core->now_time_usec ) { dst_node->unified_forwarding_send_seq = gnb_core->now_time_usec; } dst_node->unified_forwarding_send_seq++; unified_forwarding_frame_foot->unified_forwarding_seq = gnb_htonll(dst_node->unified_forwarding_send_seq); gnb_p2p_forward_payload_to_node(gnb_core, unified_forwarding_node, payload); dst_node->unified_forwarding_node_ts_sec = gnb_core->now_time_sec; GNB_LOG3(gnb_core->log, GNB_LOG_ID_PF, "*>> Unified Forwarding from tun %llu=>%llu=>%llu seq=%"PRIu64" *>>\n", gnb_core->local_node->uuid64, dst_node->unified_forwarding_nodeid, dst_node->uuid64, dst_node->unified_forwarding_send_seq); return 1; } int gnb_unified_forwarding_with_multi_path_tun(gnb_core_t *gnb_core, gnb_pf_ctx_t *pf_ctx){ int ret; int i; int c = 0; gnb_node_t *dst_node; gnb_payload16_t *payload; uint16_t in_payload_size; gnb_unified_forwarding_frame_foot_t *unified_forwarding_frame_foot; gnb_node_t *unified_forwarding_node; if ( GNB_UNIFIED_FORWARDING_HYPER != gnb_core->conf->unified_forwarding ) { if ( IPPROTO_TCP != pf_ctx->ipproto ) { ret = gnb_unified_forwarding_tun(gnb_core, pf_ctx); if ( 1 != ret && NULL != pf_ctx->dst_node ) { gnb_p2p_forward_payload_to_node(gnb_core, pf_ctx->dst_node, pf_ctx->fwd_payload); } return ret; } } dst_node = pf_ctx->dst_node; payload = pf_ctx->fwd_payload; in_payload_size = gnb_payload16_size(payload); unified_forwarding_frame_foot = ( (void *)payload ) + in_payload_size; payload->sub_type = payload->sub_type | GNB_PAYLOAD_SUB_TYPE_IPFRAME_UNIFIED_MULTI_PATH; gnb_payload16_set_size( payload, in_payload_size + sizeof(gnb_unified_forwarding_frame_foot_t) ); unified_forwarding_frame_foot->src_nodeid = gnb_htonll(gnb_core->local_node->uuid64); unified_forwarding_frame_foot->dst_nodeid = gnb_htonll(dst_node->uuid64); if ( dst_node->unified_forwarding_send_seq < gnb_core->now_time_usec ) { dst_node->unified_forwarding_send_seq = gnb_core->now_time_usec; } dst_node->unified_forwarding_send_seq++; unified_forwarding_frame_foot->unified_forwarding_seq = gnb_htonll(dst_node->unified_forwarding_send_seq); if ( NULL != pf_ctx->dst_node ) { // 先发送到目的地,然后是 unified forwarding 节点 gnb_p2p_forward_payload_to_node(gnb_core, pf_ctx->dst_node, payload); GNB_LOG3(gnb_core->log, GNB_LOG_ID_PF, "*>> Unified Forwarding with Multi-Path to tun local %llu=>%llu seq=%"PRIu64" *>>\n", gnb_core->local_node->uuid64, dst_node->uuid64, dst_node->unified_forwarding_send_seq); } for ( i=0; inow_time_sec - dst_node->unified_forwarding_node_array[i].last_ts_sec) > GNB_UNIFIED_FORWARDING_NODE_ARRAY_EXPIRED_SEC ) { continue; } dst_node->unified_forwarding_nodeid = dst_node->unified_forwarding_node_array[i].uuid64; unified_forwarding_node = GNB_HASH32_UINT64_GET_PTR(gnb_core->uuid_node_map, dst_node->unified_forwarding_nodeid); if ( NULL == unified_forwarding_node ) { continue; } unified_forwarding_frame_foot->unified_forwarding_nodeid = gnb_htonll(dst_node->unified_forwarding_nodeid); gnb_p2p_forward_payload_to_node(gnb_core, unified_forwarding_node, payload); GNB_LOG3(gnb_core->log, GNB_LOG_ID_PF, "*>> Unified Forwarding with Multi-Path to tun %llu=>%llu=>%llu seq=%"PRIu64" *>>\n", gnb_core->local_node->uuid64, dst_node->uuid64, dst_node->unified_forwarding_nodeid, dst_node->unified_forwarding_send_seq); //最多转发5个节点 if ( c >= 5 ) { break; } c++; } dst_node->unified_forwarding_node_ts_sec = gnb_core->now_time_sec; return c; } int gnb_unified_forwarding_inet(gnb_core_t *gnb_core, gnb_payload16_t *payload){ gnb_unified_forwarding_frame_foot_t *unified_forwarding_frame_foot; gnb_uuid_t src_nodeid; gnb_node_t *src_node; gnb_uuid_t dst_nodeid; gnb_node_t *dst_node; gnb_uuid_t unified_forwarding_nodeid; gnb_node_t *unified_forwarding_node; uint64_t unified_forwarding_seq; uint16_t in_payload_size; in_payload_size = gnb_payload16_size(payload); if ( in_payload_size <= sizeof(gnb_unified_forwarding_frame_foot_t) ) { GNB_LOG3(gnb_core->log, GNB_LOG_ID_PF, "Unified Forwarding inet frame error size=%u\n", in_payload_size); return UNIFIED_FORWARDING_ERROR; } unified_forwarding_frame_foot = ( (void *)payload ) + ( in_payload_size - sizeof(gnb_unified_forwarding_frame_foot_t) ); src_nodeid = gnb_ntohll(unified_forwarding_frame_foot->src_nodeid); src_node = GNB_HASH32_UINT64_GET_PTR(gnb_core->uuid_node_map, src_nodeid); if ( NULL == src_node ) { GNB_LOG3(gnb_core->log, GNB_LOG_ID_PF, "Unified Forwarding inet src node %llu not found!\n", src_nodeid); return UNIFIED_FORWARDING_ERROR; } dst_nodeid = gnb_ntohll(unified_forwarding_frame_foot->dst_nodeid); dst_node = GNB_HASH32_UINT64_GET_PTR(gnb_core->uuid_node_map, dst_nodeid); unified_forwarding_nodeid = gnb_ntohll(unified_forwarding_frame_foot->unified_forwarding_nodeid); if ( NULL == dst_node ) { GNB_LOG3(gnb_core->log, GNB_LOG_ID_PF, "Unified Forwarding inet dst node %llu not found!\n", dst_nodeid); return UNIFIED_FORWARDING_ERROR; } unified_forwarding_seq = gnb_ntohll(unified_forwarding_frame_foot->unified_forwarding_seq); //payload to inet if ( gnb_core->local_node->uuid64 != dst_nodeid ) { if ( gnb_core->local_node->type & GNB_NODE_TYPE_SLIENCE ) { return UNIFIED_FORWARDING_DROP; } gnb_p2p_forward_payload_to_node(gnb_core, dst_node, payload); GNB_LOG3(gnb_core->log, GNB_LOG_ID_PF, ">*> Unified Forwarding to inet %llu=>%llu=>%llu seq=%"PRIu64" >*>\n", src_nodeid, unified_forwarding_nodeid, dst_nodeid, unified_forwarding_seq); return UNIFIED_FORWARDING_TO_INET; } //payload to tun src_node->unified_forwarding_nodeid = unified_forwarding_nodeid; src_node->unified_forwarding_node_ts_sec = gnb_core->now_time_sec; gnb_payload16_set_size( payload, in_payload_size - sizeof(gnb_unified_forwarding_frame_foot_t) ); GNB_LOG3(gnb_core->log, GNB_LOG_ID_PF, "*<< Unified Forwarding to tun %llu=>%llu=>%llu seq=%"PRIu64" *<<\n", src_nodeid, unified_forwarding_nodeid, dst_nodeid, unified_forwarding_seq); return UNIFIED_FORWARDING_TO_TUN; } int gnb_unified_forwarding_multi_path_inet(gnb_core_t *gnb_core, gnb_payload16_t *payload){ gnb_unified_forwarding_frame_foot_t *unified_forwarding_frame_foot; gnb_uuid_t src_nodeid; gnb_node_t *src_node; gnb_uuid_t dst_nodeid; gnb_node_t *dst_node; gnb_uuid_t unified_forwarding_nodeid; gnb_node_t *unified_forwarding_node; uint64_t unified_forwarding_seq; uint16_t in_payload_size; in_payload_size = gnb_payload16_size(payload); if ( in_payload_size <= sizeof(gnb_unified_forwarding_frame_foot_t) ) { GNB_LOG3(gnb_core->log, GNB_LOG_ID_PF, "Unified Forwarding inet frame error size=%u\n", in_payload_size); return UNIFIED_FORWARDING_ERROR; } unified_forwarding_frame_foot = ( (void *)payload ) + ( in_payload_size - sizeof(gnb_unified_forwarding_frame_foot_t) ); src_nodeid = gnb_ntohll(unified_forwarding_frame_foot->src_nodeid); src_node = GNB_HASH32_UINT64_GET_PTR(gnb_core->uuid_node_map, src_nodeid); if ( NULL == src_node ) { GNB_LOG3(gnb_core->log, GNB_LOG_ID_PF, "Unified Forwarding inet src node %llu not found!\n", src_nodeid); return UNIFIED_FORWARDING_ERROR; } dst_nodeid = gnb_ntohll(unified_forwarding_frame_foot->dst_nodeid); dst_node = GNB_HASH32_UINT64_GET_PTR(gnb_core->uuid_node_map, dst_nodeid); unified_forwarding_nodeid = gnb_ntohll(unified_forwarding_frame_foot->unified_forwarding_nodeid); if ( NULL == dst_node ) { GNB_LOG3(gnb_core->log, GNB_LOG_ID_PF, "Unified Forwarding inet error dst node %llu not found!\n", dst_nodeid); return UNIFIED_FORWARDING_ERROR; } unified_forwarding_seq = gnb_ntohll(unified_forwarding_frame_foot->unified_forwarding_seq); //payload to inet if ( gnb_core->local_node->uuid64 != dst_nodeid ) { if ( gnb_core->local_node->type & GNB_NODE_TYPE_SLIENCE ) { GNB_LOG3(gnb_core->log, GNB_LOG_ID_PF, ">*> Unified Forwarding Multi Path inet local node is slience dst=%llu frame drop! >*>\n", dst_nodeid); return UNIFIED_FORWARDING_DROP; } gnb_p2p_forward_payload_to_node(gnb_core, dst_node, payload); GNB_LOG3(gnb_core->log, GNB_LOG_ID_PF, ">*> Unified Forwarding Multi Path %llu=>%llu=>%llu seq=%"PRIu64" frame to inet >*>\n", src_nodeid, unified_forwarding_nodeid, dst_nodeid, unified_forwarding_seq); return UNIFIED_FORWARDING_TO_INET; } //scan the dst node unified_forwarding_seq_array int max_seq_idx=0; int min_seq_idx=UNIFIED_FORWARDING_RECV_SEQ_ARRAY_SIZE-1; int i; for ( i=0; iunified_forwarding_recv_seq_array[i] ) { GNB_LOG3(gnb_core->log, GNB_LOG_ID_PF, "*<< Unified Forwarding Multi Path inet in_seq=%"PRIu64" == recv_seq[%d]=%"PRIu64" frame drop! *<<\n", unified_forwarding_seq, i, dst_node->unified_forwarding_recv_seq_array[i]); return UNIFIED_FORWARDING_DROP; } if ( dst_node->unified_forwarding_recv_seq_array[i] > dst_node->unified_forwarding_recv_seq_array[max_seq_idx] ) { max_seq_idx = i; } if ( dst_node->unified_forwarding_recv_seq_array[i] < dst_node->unified_forwarding_recv_seq_array[min_seq_idx] ) { min_seq_idx = i; } } if ( unified_forwarding_seq < dst_node->unified_forwarding_recv_seq_array[min_seq_idx] ) { GNB_LOG3(gnb_core->log, GNB_LOG_ID_PF, "*<< Unified Forwarding Multi Path inet %llu=>%llu=>%llu in_seq=%"PRIu64" < min_seq=%"PRIu64" frame drop! *<<\n", src_nodeid, unified_forwarding_nodeid, dst_nodeid, unified_forwarding_seq, dst_node->unified_forwarding_recv_seq_array[min_seq_idx]); return UNIFIED_FORWARDING_DROP; } if ( unified_forwarding_seq > dst_node->unified_forwarding_recv_seq_array[max_seq_idx] ) { GNB_LOG3(gnb_core->log, GNB_LOG_ID_PF, "*<< Unified Forwarding multi path inet %llu=>%llu=>%llu in_seq=%"PRIu64" > max_seq=%"PRIu64" frame to tun *<<\n", src_nodeid, unified_forwarding_nodeid, dst_nodeid, unified_forwarding_seq, dst_node->unified_forwarding_recv_seq_array[max_seq_idx]); } else { GNB_LOG3(gnb_core->log, GNB_LOG_ID_PF, "*<< Unified Forwarding Multi Path inet %llu=>%llu=>%llu in_seq=%"PRIu64" < max_seq=%"PRIu64" frame to tun *<<\n", src_nodeid, unified_forwarding_nodeid, dst_nodeid, unified_forwarding_seq, dst_node->unified_forwarding_recv_seq_array[max_seq_idx]); } dst_node->unified_forwarding_recv_seq_array[min_seq_idx] = unified_forwarding_seq; //payload to tun src_node->unified_forwarding_nodeid = unified_forwarding_nodeid; src_node->unified_forwarding_node_ts_sec = gnb_core->now_time_sec; gnb_payload16_set_size( payload, in_payload_size - sizeof(gnb_unified_forwarding_frame_foot_t) ); return UNIFIED_FORWARDING_TO_TUN; } opengnb-ver1.6.0.a/src/gnb_unified_forwarding.h000077500000000000000000000030001500454252100215270ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 . */ #ifndef GNB_UNIFIED_FORWARDING_H #define GNB_UNIFIED_FORWARDING_H #include typedef struct _gnb_core_t gnb_core_t; typedef struct _gnb_payload16_t gnb_payload16_t; typedef struct _gnb_node_t gnb_node_t; typedef struct _gnb_sockaddress_t gnb_sockaddress_t; int gnb_unified_forwarding_tun(gnb_core_t *gnb_core, gnb_pf_ctx_t *pf_ctx); int gnb_unified_forwarding_with_multi_path_tun(gnb_core_t *gnb_core, gnb_pf_ctx_t *pf_ctx); #define UNIFIED_FORWARDING_DROP -2 #define UNIFIED_FORWARDING_ERROR -1 #define UNIFIED_FORWARDING_TO_TUN 0 #define UNIFIED_FORWARDING_TO_INET 1 void gnb_setup_unified_forwarding_nodeid(gnb_core_t *gnb_core, gnb_node_t *dst_node); int gnb_unified_forwarding_inet(gnb_core_t *gnb_core, gnb_payload16_t *payload); int gnb_unified_forwarding_multi_path_inet(gnb_core_t *gnb_core, gnb_payload16_t *payload); #endif opengnb-ver1.6.0.a/src/gnb_ur1_frame_type.h000077500000000000000000000031041500454252100206110ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 . */ #ifndef GNB_UR1_FRAME_TYPE_H #define GNB_UR1_FRAME_TYPE_H #include "stdint.h" #include "gnb_type.h" #include "gnb_core_frame_type_defs.h" #pragma pack(push, 1) typedef struct _gnb_ur1_frame_head_t{ gnb_uuid_t src_uuid64; //由第一个转发的node设置,应用构造时设置为0, 网络字节序 gnb_uuid_t dst_uuid64; //由应用构造时设置,网络字节序 uint8_t src_addr[16]; //src_addr,src_port 由转发的node设置 uint16_t src_port; //网络字节序 uint8_t dst_addr[16]; //由应用构造时设置 uint16_t dst_port; //网络字节序 unsigned char passcode[4]; unsigned char verifycode[4]; //由第一个转发的node设置 uint8_t ttl; //由第一个转发的node设置为2, 应用构造时设置为0, }__attribute__ ((__packed__)) gnb_ur1_frame_head_t; #pragma pack(pop) #define GNB_MAX_UR1_FRAME_SIZE (32*1024) #endif opengnb-ver1.6.0.a/src/gnb_worker.c000077500000000000000000000063741500454252100172070ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 #include #include #include #include #include "gnb.h" #include "gnb_worker.h" #include "gnb_worker_queue_data.h" /* 每个 worker 都是一个独立线程,设计上允许多个线程并发处理payload,但对于处理 node 的数据来说不是很必要。 如果把 pf 也设计为 worker 的形式,对于加密运算比较重的分组,可以发挥多核的特性 */ extern gnb_worker_t gnb_primary_worker_mod; extern gnb_worker_t gnb_node_worker_mod; extern gnb_worker_t gnb_index_worker_mod; extern gnb_worker_t gnb_secure_index_worker_mod; extern gnb_worker_t gnb_detect_worker_mod; extern gnb_worker_t gnb_index_service_worker_mod; extern gnb_worker_t gnb_secure_index_service_worker_mod; extern gnb_worker_t gnb_pf_worker_mod; static gnb_worker_t *gnb_worker_array[] = { &gnb_primary_worker_mod, &gnb_index_worker_mod, &gnb_secure_index_worker_mod, &gnb_index_service_worker_mod, &gnb_secure_index_service_worker_mod, &gnb_detect_worker_mod, &gnb_node_worker_mod, &gnb_pf_worker_mod, NULL, }; static gnb_worker_t* find_worker_mod_by_name(const char *name){ int num = sizeof(gnb_worker_array)/sizeof(gnb_worker_t *); int i; for ( i=0; iname,name,128) ) { return gnb_worker_array[i]; } } return NULL; } gnb_worker_t *gnb_worker_init(const char *name, void *ctx){ gnb_worker_t *gnb_worker_mod = find_worker_mod_by_name(name); if ( NULL==gnb_worker_mod ) { printf("find_worker_by_name name[%s] is NULL\n",name); return NULL; } gnb_worker_t *gnb_worker = (gnb_worker_t *) malloc(sizeof(gnb_worker_t)); *gnb_worker = *gnb_worker_mod; gnb_worker->thread_worker_flag = 0; gnb_worker->thread_worker_run_flag = 0; gnb_worker->init(gnb_worker, ctx); return gnb_worker; } void gnb_worker_wait_primary_worker_started(gnb_core_t *gnb_core){ do{ if ( 1==gnb_core->primary_worker->thread_worker_run_flag ) { break; } }while(1); } void gnb_worker_sync_time(uint64_t *now_time_sec_ptr, uint64_t *now_time_usec_ptr){ struct timeval now_timeval; gettimeofday(&now_timeval, NULL); *now_time_sec_ptr = (uint64_t)now_timeval.tv_sec; *now_time_usec_ptr = (uint64_t)now_timeval.tv_sec *1000000 + now_timeval.tv_usec; } void gnb_worker_release(gnb_worker_t *gnb_worker){ gnb_worker->release(gnb_worker); free(gnb_worker); return; } opengnb-ver1.6.0.a/src/gnb_worker.h000077500000000000000000000017751500454252100172140ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 . */ #ifndef GNB_WORKER_H #define GNB_WORKER_H #include "gnb_worker_type.h" gnb_worker_t *gnb_worker_init(const char *name, void *ctx); void gnb_worker_wait_primary_worker_started(gnb_core_t *gnb_core); void gnb_worker_sync_time(uint64_t *now_time_sec_ptr, uint64_t *now_time_usec_ptr); void gnb_worker_release(gnb_worker_t *gnb_worker); #endif opengnb-ver1.6.0.a/src/gnb_worker_queue_data.h000077500000000000000000000031371500454252100214030ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 . */ #ifndef GNB_NODE_WORKER_QUEUE_DATA_H #define GNB_NODE_WORKER_QUEUE_DATA_H #include typedef struct _gnb_node_t gnb_node_t; typedef struct _gnb_payload16_t gnb_payload16_t; typedef struct _gnb_sockaddress_t gnb_sockaddress_t; typedef struct _gnb_node_worker_in_data_t { gnb_sockaddress_t node_addr_st; uint8_t socket_idx; gnb_payload16_t payload_st; }gnb_worker_in_data_t; typedef struct _gnb_worker_queue_data_t { #define GNB_WORKER_QUEUE_DATA_TYPE_NODE_IN 0x1 #define GNB_WORKER_QUEUE_DATA_TYPE_NODE_OUT 0x2 int type; union worker_data { gnb_worker_in_data_t node_in; }data; //这里可以定义宏方便操作union }gnb_worker_queue_data_t; //这个块不能太大,在嵌入设备上,这里是占用内存的大头 #define GNB_NODE_WORKER_QUEUE_BLOCK_SIZE 512 #define GNB_INDEX_WORKER_QUEUE_BLOCK_SIZE 512 #define GNB_INDEX_SERVICE_WORKER_QUEUE_BLOCK_SIZE 512 #endif opengnb-ver1.6.0.a/src/gnb_worker_type.h000077500000000000000000000035331500454252100202470ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 . */ #ifndef GNB_WORKER_TYPE_H #define GNB_WORKER_TYPE_H #include #include "gnb_ring_buffer_fixed.h" typedef struct _gnb_worker_t gnb_worker_t; typedef struct _gnb_ring_buffer_t gnb_ring_buffer_t; typedef void(*gnb_worker_init_func_t)(gnb_worker_t *gnb_worker, void *ctx); typedef void(*gnb_worker_release_func_t)(gnb_worker_t *gnb_worker); typedef int(*gnb_worker_start_func_t)(gnb_worker_t *gnb_worker); typedef int(*gnb_worker_stop_func_t)(gnb_worker_t *gnb_worker); typedef int(*gnb_worker_notify_func_t)(gnb_worker_t *gnb_worker); typedef int(*gnb_worker_notify_func_t)(gnb_worker_t *gnb_worker); typedef struct _gnb_worker_t { char *name; gnb_worker_init_func_t init; gnb_worker_release_func_t release; gnb_worker_start_func_t start; gnb_worker_stop_func_t stop; gnb_worker_notify_func_t notify; gnb_ring_buffer_fixed_t *ring_buffer_in; gnb_ring_buffer_fixed_t *ring_buffer_out; volatile int thread_worker_flag; volatile int thread_worker_ready_flag; volatile int thread_worker_run_flag; void *ctx; }gnb_worker_t; typedef struct _gnb_worker_ring_t { uint8_t size; uint8_t cur_idx; gnb_worker_t *worker[0]; }gnb_worker_ring_t; #endif opengnb-ver1.6.0.a/src/linux/000077500000000000000000000000001500454252100160265ustar00rootroot00000000000000opengnb-ver1.6.0.a/src/linux/gnb_drv_linux.c000077500000000000000000000162211500454252100210370ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "gnb.h" #include "gnb_arg_list.h" #include "gnb_exec.h" #include "gnb_tun_drv.h" #include "gnb_payload16.h" void bind_socket_if(gnb_core_t *gnb_core){ if ( '\0' == gnb_core->conf->socket_ifname[0] ) { return; } struct ifreq nif; memset(&nif,0,sizeof(struct ifreq)); strncpy(nif.ifr_name, gnb_core->conf->socket_ifname, IFNAMSIZ); int i; for ( i=0; i < gnb_core->conf->udp6_socket_num; i++ ) { setsockopt(gnb_core->udp_ipv6_sockets[i], SOL_SOCKET, SO_BINDTODEVICE, (char *)&nif, sizeof(nif)); } for ( i=0; i < gnb_core->conf->udp4_socket_num; i++ ) { setsockopt(gnb_core->udp_ipv4_sockets[i], SOL_SOCKET, SO_BINDTODEVICE, (char *)&nif, sizeof(nif)); } } static void if_up_script(gnb_core_t *gnb_core){ int ret; char cmd[PATH_MAX+NAME_MAX]; snprintf(cmd,PATH_MAX+NAME_MAX,"\"%s/scripts/%s\" > /dev/null 2>&1",gnb_core->conf->conf_dir,"if_up_linux.sh"); ret = system(cmd); if ( -1==ret || 0 ==ret ) { return; } return; } static void if_down_script(gnb_core_t *gnb_core){ int ret; char cmd[PATH_MAX+NAME_MAX]; snprintf(cmd,PATH_MAX+NAME_MAX,"\"%s/scripts/%s\" > /dev/null 2>&1",gnb_core->conf->conf_dir,"if_down_linux.sh"); ret = system(cmd); if ( -1==ret || 0 ==ret ) { return; } return; } static void setifmtu(char *if_name,int mtu) { int socket_fd; struct ifreq ifr; memset(&ifr,0,sizeof(struct ifreq)); strncpy(ifr.ifr_name, if_name, IFNAMSIZ); ifr.ifr_mtu = mtu; if ( (socket_fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) { perror("socket "); } int ret = ioctl(socket_fd, SIOCSIFMTU, &ifr); if ( -1==ret ) { perror("ioctl"); } close(socket_fd); } static int set_addr4(char *interface_name, char *ip, char *netmask){ int socket_fd; if ( (socket_fd = socket(PF_INET, SOCK_STREAM, 0)) < 0 ) { return -1; } struct ifreq ifr; strncpy(ifr.ifr_name, interface_name, IFNAMSIZ); struct sockaddr_in addr; bzero(&addr, sizeof(struct sockaddr_in)); addr.sin_family = PF_INET; inet_aton(ip, &addr.sin_addr); memcpy(&ifr.ifr_ifru.ifru_addr, &addr, sizeof(struct sockaddr_in)); if ( ioctl(socket_fd, SIOCSIFADDR, &ifr) < 0 ) { perror("ioctl addr4 SIOCSIFADDR"); exit(1); } struct ifreq ifr_mask; memset(&ifr_mask, 0, sizeof(struct ifreq)); strncpy(ifr_mask.ifr_name, interface_name, IFNAMSIZ); struct sockaddr_in *sin_net_mask; sin_net_mask = (struct sockaddr_in *)&ifr_mask.ifr_addr; sin_net_mask -> sin_family = AF_INET; inet_pton(AF_INET, netmask, &sin_net_mask ->sin_addr); if ( ioctl(socket_fd, SIOCSIFNETMASK, &ifr_mask ) < 0 ) { perror("ioctl addr4 SIOCSIFNETMASK"); exit(1); } close(socket_fd); return 0; } static int set_addr6(char *interface_name, char *ip, char *netmask){ struct ifreq ifr; struct in6_ifreq ifr6; int socket_fd; int ret; memset(&ifr, 0, sizeof(struct ifreq)); memset(&ifr6, 0, sizeof(struct in6_ifreq)); socket_fd = socket(PF_INET6, SOCK_DGRAM, IPPROTO_IP); if ( socket_fd < 0 ) { return -1; } strncpy(ifr.ifr_name, interface_name, IFNAMSIZ); ret = ioctl(socket_fd, SIOGIFINDEX, &ifr); if ( ret< 0 ) { goto finish; } ifr6.ifr6_ifindex = ifr.ifr_ifindex; inet_pton(AF_INET6, ip, (void *)&ifr6.ifr6_addr); ifr6.ifr6_prefixlen = 96; ret = ioctl(socket_fd, SIOCSIFADDR, &ifr6); if ( ret< 0 ) { goto finish; } finish: close(socket_fd); return ret; } static int interface_up(char *interface_name) { int socket_fd; if ( (socket_fd = socket(PF_INET,SOCK_STREAM,0)) < 0 ) { return -1; } struct ifreq ifr; strncpy(ifr.ifr_name,interface_name,IFNAMSIZ); short flag; flag = IFF_UP; if ( ioctl(socket_fd, SIOCGIFFLAGS, &ifr) < 0 ) { return -2; } ifr.ifr_ifru.ifru_flags |= flag; if ( ioctl(socket_fd, SIOCSIFFLAGS, &ifr) < 0 ) { return -3; } close(socket_fd); return 0; } static int tun_alloc(char *dev) { struct ifreq ifr; int fd, err; char *clonedev = "/dev/net/tun"; if ( (fd = open(clonedev , O_RDWR)) < 0 ) { return fd; } memset(&ifr, 0, sizeof(ifr)); ifr.ifr_flags = IFF_TUN | IFF_NO_PI; strncpy(ifr.ifr_name, dev, IFNAMSIZ); if ( (err = ioctl(fd, TUNSETIFF, (void *)&ifr)) < 0 ) { //perror("ioctl(TUNSETIFF)"); close(fd); return err; } return fd; } int init_tun_linux(gnb_core_t *gnb_core){ gnb_core->tun_fd = -1; return 0; } static int open_tun_linux(gnb_core_t *gnb_core){ if ( -1 != gnb_core->tun_fd ) { return -1; } gnb_core->tun_fd = tun_alloc(gnb_core->ifname); set_addr4(gnb_core->ifname, GNB_ADDR4STR_PLAINTEXT1(&gnb_core->local_node->tun_addr4), GNB_ADDR4STR_PLAINTEXT2(&gnb_core->local_node->tun_netmask_addr4)); if ( GNB_ADDR_TYPE_IPV4 != gnb_core->conf->udp_socket_type ) { set_addr6(gnb_core->ifname, GNB_ADDR6STR_PLAINTEXT1(&gnb_core->local_node->tun_ipv6_addr), "FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:0000:0000"); } interface_up(gnb_core->ifname); setifmtu(gnb_core->ifname, gnb_core->conf->mtu); if_up_script(gnb_core); return 0; } static int read_tun_linux(gnb_core_t *gnb_core, void *buf, size_t buf_size){ ssize_t rlen; rlen = read(gnb_core->tun_fd, buf, buf_size); return rlen; } static int write_tun_linux(gnb_core_t *gnb_core, void *buf, size_t buf_size){ ssize_t wlen; wlen = write(gnb_core->tun_fd, buf, buf_size); return wlen; } static int close_tun_linux(gnb_core_t *gnb_core){ close(gnb_core->tun_fd); gnb_core->tun_fd = -1; if_down_script(gnb_core); return 0; } static int release_tun_linux(gnb_core_t *gnb_core){ free(gnb_core->platform_ctx); return 0; } gnb_tun_drv_t gnb_tun_drv_linux = { init_tun_linux, open_tun_linux, read_tun_linux, write_tun_linux, close_tun_linux, release_tun_linux }; opengnb-ver1.6.0.a/src/mingw/000077500000000000000000000000001500454252100160105ustar00rootroot00000000000000opengnb-ver1.6.0.a/src/mingw/gnb.exe.manifest000077500000000000000000000006411500454252100210720ustar00rootroot00000000000000 opengnb-ver1.6.0.a/src/mingw/gnb_drv_win32.c000077500000000000000000000370711500454252100206320ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 #include #include #undef _WIN32_WINNT #define _WIN32_WINNT 0x0600 #include #include #include #include #include #include "tap-windows/tap-windows.h" #include "gnb.h" #include "gnb_exec.h" #include "gnb_tun_drv.h" #include "gnb_payload16.h" typedef struct _gnb_core_win_ctx_t{ char tap_file_name[PATH_MAX]; char if_name[PATH_MAX]; char deviceid[PATH_MAX]; ULONG tun_if_id; HANDLE device_handle; OVERLAPPED read_olpd; OVERLAPPED write_olpd; int skip_if_script; }gnb_core_win_ctx_t; static int close_tun_win32(gnb_core_t *gnb_core); static int open_tun_win32(gnb_core_t *gnb_core); #define MAX_KEY_LENGTH 255 /* {xxxxxxxxxxxx} 形式的字符串 */ static char *get_if_deviceid() { HKEY adapters, adapter; DWORD i, ret, len; char *deviceid = NULL; DWORD sub_keys = 0; ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT(ADAPTER_KEY), 0, KEY_READ, &adapters); if (ret != ERROR_SUCCESS) { return NULL; } ret = RegQueryInfoKey(adapters, NULL, NULL, NULL, &sub_keys, NULL, NULL, NULL, NULL, NULL, NULL, NULL); if (ret != ERROR_SUCCESS) { return NULL; } if (sub_keys <= 0) { return NULL; } /* Walk througt all adapters */ for (i = 0; i < sub_keys; i++) { char new_key[MAX_KEY_LENGTH]; char data[256]; TCHAR key[MAX_KEY_LENGTH]; DWORD keylen = MAX_KEY_LENGTH; /* Get the adapter key name */ ret = RegEnumKeyEx(adapters, i, key, &keylen, NULL, NULL, NULL, NULL); if (ret != ERROR_SUCCESS) { continue; } /* Append it to NETWORK_ADAPTERS and open it */ snprintf(new_key, sizeof(new_key), "%s\\%s", ADAPTER_KEY, key); ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT(new_key), 0, KEY_READ, &adapter); if (ret != ERROR_SUCCESS) { continue; } len = sizeof(data); ret = RegQueryValueEx(adapter, "DriverDesc", NULL, NULL, (LPBYTE)data, &len); if (ret != ERROR_SUCCESS) { goto clean; } if (strncmp(data, "TAP-Windows", sizeof("TAP-Windows")-1) == 0) { DWORD type; len = sizeof(data); ret = RegQueryValueEx(adapter, "NetCfgInstanceId", NULL, &type, (LPBYTE)data, &len); if (ret != ERROR_SUCCESS) { goto clean; } deviceid = strdup(data); break; } clean: RegCloseKey(adapter); } RegCloseKey(adapters); return deviceid; } /* 网络连接的名字 */ static char* get_if_devicename(const char *if_deviceid){ HKEY key; DWORD ret; char regpath[MAX_KEY_LENGTH]; char devicename[PATH_MAX]; long name_len = PATH_MAX; snprintf(regpath, MAX_KEY_LENGTH, "%s\\%s\\Connection", NETWORK_CONNECTIONS_KEY, if_deviceid); ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT(regpath), 0, KEY_READ, &key); if (ret != ERROR_SUCCESS) { RegCloseKey(key); return NULL; } ret = RegQueryValueEx(key, "Name", 0, 0, devicename, &name_len); if (ret != ERROR_SUCCESS) { RegCloseKey(key); return NULL; } RegCloseKey(key); return strdup(devicename); } int init_tun_win32(gnb_core_t *gnb_core){ char *deviceid; char *devicename; gnb_core_win_ctx_t *tun_win_ctx = (gnb_core_win_ctx_t *)malloc(sizeof(gnb_core_win_ctx_t)); tun_win_ctx->skip_if_script = 0; tun_win_ctx->device_handle = INVALID_HANDLE_VALUE; gnb_core->platform_ctx = tun_win_ctx; deviceid = get_if_deviceid(); if ( NULL==deviceid ) { return -1; } snprintf(tun_win_ctx->deviceid, PATH_MAX, "%s", deviceid); snprintf(tun_win_ctx->tap_file_name, PATH_MAX, "%s%s%s", USERMODEDEVICEDIR, deviceid, TAP_WIN_SUFFIX); devicename = get_if_devicename(deviceid); if ( NULL != devicename ) { snprintf(tun_win_ctx->if_name, PATH_MAX, "%s", devicename); free(devicename); } if ( tun_win_ctx->if_name && 0 != strncmp(gnb_core->ifname,tun_win_ctx->if_name,256) ) { snprintf(gnb_core->ifname, 256, "%s", tun_win_ctx->if_name); } snprintf(gnb_core->if_device_string, 256, "%s", deviceid); free(deviceid); return 0; } #define WORKING_BUFFER_SIZE 15000 #define MAX_TRIES 3 #define MALLOC(x) HeapAlloc(GetProcessHeap(), 0, (x)) #define FREE(x) HeapFree(GetProcessHeap(), 0, (x)) /* 网络接口id */ static ULONG get_if_id(gnb_core_t *gnb_core){ gnb_core_win_ctx_t *tun_win_ctx = gnb_core->platform_ctx; ULONG family = AF_UNSPEC; //AF_INET AF_INET6 AF_UNSPEC DWORD dwRetVal = 0; ULONG outBufLen = 0; ULONG Iterations = 0; ULONG flags = GAA_FLAG_INCLUDE_PREFIX | GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_INCLUDE_GATEWAYS; outBufLen = WORKING_BUFFER_SIZE; PIP_ADAPTER_ADDRESSES pAddresses = NULL; PIP_ADAPTER_ADDRESSES pCurrAddresses = NULL; struct sockaddr_in *sa_in; struct sockaddr_in6 *sa_in6; do { pAddresses = (IP_ADAPTER_ADDRESSES *)MALLOC(outBufLen); if (pAddresses == NULL) { GNB_LOG3(gnb_core->log, GNB_LOG_ID_CORE, "Memory allocation failed for IP_ADAPTER_ADDRESSES struct\n"); exit(1); } dwRetVal = GetAdaptersAddresses(family, flags, NULL, pAddresses, &outBufLen); if (dwRetVal == ERROR_BUFFER_OVERFLOW) { FREE(pAddresses); pAddresses = NULL; } else { break; } Iterations++; } while ((dwRetVal == ERROR_BUFFER_OVERFLOW) && (Iterations < MAX_TRIES)); if (dwRetVal != NO_ERROR) { return 0l; } pCurrAddresses = pAddresses; char friendlyname_string[256]; char description_string[256]; char ipv4_string[INET_ADDRSTRLEN]; char ipv6_string[INET6_ADDRSTRLEN]; tun_win_ctx->tun_if_id = -1; while (pCurrAddresses) { if (IfOperStatusUp != pCurrAddresses->OperStatus) { goto next; } WideCharToMultiByte(CP_ACP,WC_COMPOSITECHECK,pCurrAddresses->Description,-1,description_string,256,NULL,NULL); WideCharToMultiByte(CP_ACP,WC_COMPOSITECHECK,pCurrAddresses->FriendlyName,-1,friendlyname_string,256,NULL,NULL); if ( 0==strncmp( description_string,"TAP-Windows Adapter V9", sizeof("TAP-Windows Adapter V9")-1 ) ) { //需要比较 pCurrAddresses->AdapterName 找出真正的 tun_if_id if ( !strncmp(pCurrAddresses->AdapterName, tun_win_ctx->deviceid, PATH_MAX) ) { return pCurrAddresses->IfIndex; } goto next; } next: pCurrAddresses = pCurrAddresses->Next; } FREE(pAddresses); return 0l; } static void if_up(gnb_core_t *gnb_core){ char bin_path[PATH_MAX+NAME_MAX]; char bin_path_q[PATH_MAX+NAME_MAX]; char map_path_q[PATH_MAX+NAME_MAX]; gnb_core_win_ctx_t *tun_win_ctx = gnb_core->platform_ctx; strncpy(gnb_core->ctl_block->conf_zone->conf_st.ifname, tun_win_ctx->if_name, NAME_MAX); snprintf(bin_path, PATH_MAX+NAME_MAX, "%s\\gnb_es.exe", gnb_core->ctl_block->conf_zone->conf_st.binary_dir); snprintf(bin_path_q, PATH_MAX+NAME_MAX, "\"%s\\gnb_es.exe\"", gnb_core->ctl_block->conf_zone->conf_st.binary_dir); snprintf(map_path_q, PATH_MAX+NAME_MAX, "\"%s\"", gnb_core->ctl_block->conf_zone->conf_st.map_file); gnb_arg_list_t *arg_list; arg_list = gnb_arg_list_init(32); gnb_arg_append(arg_list, bin_path_q); gnb_arg_append(arg_list, "-b"); gnb_arg_append(arg_list, map_path_q); gnb_arg_append(arg_list, "--if-up"); gnb_exec(bin_path, gnb_core->ctl_block->conf_zone->conf_st.binary_dir, arg_list, GNB_EXEC_BACKGROUND|GNB_EXEC_WAIT); gnb_arg_list_release(arg_list); } static void if_down(gnb_core_t *gnb_core){ gnb_core_win_ctx_t *tun_win_ctx = gnb_core->platform_ctx; char bin_path[PATH_MAX+NAME_MAX]; char bin_path_q[PATH_MAX+NAME_MAX]; char map_path_q[PATH_MAX+NAME_MAX]; snprintf(bin_path, PATH_MAX+NAME_MAX, "%s\\gnb_es.exe", gnb_core->ctl_block->conf_zone->conf_st.binary_dir); snprintf(bin_path_q, PATH_MAX+NAME_MAX, "\"%s\\gnb_es.exe\"", gnb_core->ctl_block->conf_zone->conf_st.binary_dir); snprintf(map_path_q, PATH_MAX+NAME_MAX, "\"%s\"", gnb_core->ctl_block->conf_zone->conf_st.map_file); gnb_arg_list_t *arg_list; arg_list = gnb_arg_list_init(32); gnb_arg_append(arg_list, bin_path_q); gnb_arg_append(arg_list, "-b"); gnb_arg_append(arg_list, map_path_q); gnb_arg_append(arg_list, "--if-down"); gnb_exec(bin_path, gnb_core->ctl_block->conf_zone->conf_st.binary_dir, arg_list, GNB_EXEC_BACKGROUND|GNB_EXEC_WAIT); gnb_arg_list_release(arg_list); } static int ntod(uint32_t mask) { int i, n = 0; int bits = sizeof(uint32_t) * 8; for (i = bits - 1; i >= 0; i--) { if (mask & (0x01 << i)) n++; } return n; } static int set_addr4(gnb_core_t *gnb_core){ gnb_core_win_ctx_t *tun_win_ctx = gnb_core->platform_ctx; DWORD dwRetVal = 0; DWORD dwSize = 0; unsigned long status = 0; DWORD lastError = 0; SOCKADDR_IN localAddress; MIB_UNICASTIPADDRESS_ROW ipRow; InitializeUnicastIpAddressEntry( &ipRow ); ipRow.InterfaceIndex = tun_win_ctx->tun_if_id; ipRow.Address.si_family = AF_INET; ipRow.OnLinkPrefixLength = (UINT8)ntod( gnb_core->local_node->tun_netmask_addr4.s_addr ); InetPton(AF_INET, GNB_ADDR4STR_PLAINTEXT1(&gnb_core->local_node->tun_addr4), &ipRow.Address.Ipv4.sin_addr); status = DeleteUnicastIpAddressEntry(&ipRow); status = CreateUnicastIpAddressEntry(&ipRow); return 0; } static int set_addr6(gnb_core_t *gnb_core){ gnb_core_win_ctx_t *tun_win_ctx = gnb_core->platform_ctx; DWORD dwRetVal = 0; DWORD dwSize = 0; unsigned long status = 0; DWORD lastError = 0; SOCKADDR_IN localAddress; MIB_UNICASTIPADDRESS_ROW ipRow; InitializeUnicastIpAddressEntry( &ipRow ); ipRow.InterfaceIndex = tun_win_ctx->tun_if_id; ipRow.Address.si_family = AF_INET6; ipRow.OnLinkPrefixLength = 96; InetPton(AF_INET6, GNB_ADDR6STR_PLAINTEXT1(&gnb_core->local_node->tun_ipv6_addr), &ipRow.Address.Ipv6.sin6_addr); status = DeleteUnicastIpAddressEntry(&ipRow); status = CreateUnicastIpAddressEntry(&ipRow); return 0; } static int open_tun_win32(gnb_core_t *gnb_core){ gnb_core_win_ctx_t *tun_win_ctx = gnb_core->platform_ctx; int ret; if ( INVALID_HANDLE_VALUE != tun_win_ctx->device_handle ) { return -1; } tun_win_ctx->device_handle = CreateFile(tun_win_ctx->tap_file_name, GENERIC_WRITE|GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM|FILE_FLAG_OVERLAPPED, 0); if ( INVALID_HANDLE_VALUE == tun_win_ctx->device_handle ) { return -2; } ULONG data[4]; DWORD len; data[0] = 1; ret = DeviceIoControl(tun_win_ctx->device_handle, TAP_WIN_IOCTL_SET_MEDIA_STATUS, data, sizeof(data), data, sizeof(data), &len, NULL); if ( ret == 0 ) { //GetLastError(); return -4; } if ( data[0]>0 ) { GNB_LOG3(gnb_core->log, GNB_LOG_ID_CORE, "Device[%s] up succeed\n", tun_win_ctx->tap_file_name); } tun_win_ctx->read_olpd.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); tun_win_ctx->write_olpd.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); tun_win_ctx->tun_if_id = get_if_id(gnb_core); gnb_core->ctl_block->core_zone->tun_if_id = tun_win_ctx->tun_if_id; int netmask = gnb_core->local_node->tun_netmask_addr4.s_addr; data[0] = gnb_core->local_node->tun_addr4.s_addr; data[1] = data[0] & netmask; data[2] = netmask; ret = DeviceIoControl(tun_win_ctx->device_handle, TAP_WIN_IOCTL_CONFIG_TUN, &data, sizeof(data), &data, sizeof(data), &len, NULL); if ( 0==ret ) { return -5; } if ( tun_win_ctx->tun_if_id > 0 ) { set_addr4(gnb_core); set_addr6(gnb_core); } if ( !tun_win_ctx->skip_if_script ) { if_up(gnb_core); } return 0; } static int read_tun_win32(gnb_core_t *gnb_core, void *buf, size_t buf_size){ gnb_core_win_ctx_t *tun_win_ctx = gnb_core->platform_ctx; int res; DWORD frame_size = 0; res = ReadFile(tun_win_ctx->device_handle, buf, buf_size, &frame_size, &tun_win_ctx->read_olpd); if (!res) { res = WaitForSingleObject(tun_win_ctx->read_olpd.hEvent, INFINITE); //res = WaitForSingleObject(tun_win_ctx->read_olpd.hEvent, 100); if ( WAIT_TIMEOUT == res ) { frame_size = -1; goto finish; } res = GetOverlappedResult(tun_win_ctx->device_handle, &tun_win_ctx->read_olpd, (LPDWORD) &frame_size, FALSE); if ( frame_size<=0 ) { tun_win_ctx->skip_if_script = 0; close_tun_win32(gnb_core); open_tun_win32(gnb_core); tun_win_ctx->skip_if_script = 1; GNB_ERROR3(gnb_core->log,GNB_LOG_ID_CORE,"read_tun_win32 ERROR frame_size=%d\n", frame_size); goto finish; } } else { goto finish; } finish: return frame_size; } static int write_tun_win32(gnb_core_t *gnb_core, void *buf, size_t buf_size){ gnb_core_win_ctx_t *tun_win_ctx = gnb_core->platform_ctx; DWORD written; int res; res = WriteFile(tun_win_ctx->device_handle, buf, buf_size, &written, &tun_win_ctx->write_olpd); if (!res && GetLastError() == ERROR_IO_PENDING) { WaitForSingleObject(tun_win_ctx->write_olpd.hEvent, INFINITE); res = GetOverlappedResult(tun_win_ctx->device_handle, &tun_win_ctx->write_olpd, &written, FALSE); if ( written != buf_size ) { GNB_ERROR3(gnb_core->log, GNB_LOG_ID_CORE, "write_tun_win32 ERROR buf_size=%d written=%d\n", buf_size,written); return -1; } } return 0; } static int close_tun_win32(gnb_core_t *gnb_core){ gnb_core_win_ctx_t *tun_win_ctx = gnb_core->platform_ctx; if (INVALID_HANDLE_VALUE==tun_win_ctx->device_handle){ GNB_ERROR3(gnb_core->log, GNB_LOG_ID_CORE,"if[%s] aready closeed\n", gnb_core->ifname); return 0; } int ret; unsigned long status = 0l; DWORD len; ret = DeviceIoControl(tun_win_ctx->device_handle, TAP_WIN_IOCTL_SET_MEDIA_STATUS, &status, sizeof(status), &status, sizeof(status), &len, NULL); if ( ret == 0 ) { //GetLastError(); return -1; } if ( status>0 ) { GNB_LOG3(gnb_core->log, GNB_LOG_ID_CORE, "Device[%s] down succeed\n",tun_win_ctx->tap_file_name); } CloseHandle(tun_win_ctx->device_handle); tun_win_ctx->device_handle = INVALID_HANDLE_VALUE; if ( !tun_win_ctx->skip_if_script ) { if_down(gnb_core); } return 0; } static int release_tun_win32(gnb_core_t *gnb_core){ free(gnb_core->platform_ctx); return 0; } gnb_tun_drv_t gnb_tun_drv_win32 = { init_tun_win32, open_tun_win32, read_tun_win32, write_tun_win32, close_tun_win32, release_tun_win32 }; opengnb-ver1.6.0.a/src/mingw/gnb_drv_wintun.c000077500000000000000000000405231500454252100212100ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 #include #include #include #include #undef _WIN32_WINNT #define _WIN32_WINNT 0x0600 #define WIN32_LEAN_AND_MEAN #include #include #include #include #include #include #include #include #include #include "wintun/wintun.h" #include "gnb.h" #include "gnb_exec.h" #include "gnb_tun_drv.h" #include "gnb_payload16.h" #define WORKING_BUFFER_SIZE 15000 #define MAX_TRIES 3 #define MALLOC(x) HeapAlloc(GetProcessHeap(), 0, (x)) #define FREE(x) HeapFree(GetProcessHeap(), 0, (x)) #define WINTUN_POOL_NAME L"GNB" #define WINTUN_RING_CAPACITY 0x400000 /* 4 MiB */ static WINTUN_CREATE_ADAPTER_FUNC *WintunCreateAdapter; static WINTUN_CLOSE_ADAPTER_FUNC *WintunCloseAdapter; static WINTUN_OPEN_ADAPTER_FUNC *WintunOpenAdapter; static WINTUN_GET_ADAPTER_LUID_FUNC *WintunGetAdapterLUID; static WINTUN_GET_RUNNING_DRIVER_VERSION_FUNC *WintunGetRunningDriverVersion; static WINTUN_DELETE_DRIVER_FUNC *WintunDeleteDriver; static WINTUN_SET_LOGGER_FUNC *WintunSetLogger; static WINTUN_START_SESSION_FUNC *WintunStartSession; static WINTUN_END_SESSION_FUNC *WintunEndSession; static WINTUN_GET_READ_WAIT_EVENT_FUNC *WintunGetReadWaitEvent; static WINTUN_RECEIVE_PACKET_FUNC *WintunReceivePacket; static WINTUN_RELEASE_RECEIVE_PACKET_FUNC *WintunReleaseReceivePacket; static WINTUN_ALLOCATE_SEND_PACKET_FUNC *WintunAllocateSendPacket; static WINTUN_SEND_PACKET_FUNC *WintunSendPacket; static HMODULE InitializeWintun(gnb_core_t *gnb_core){ GNB_LOG3(gnb_core->log, GNB_LOG_ID_CORE, "LoadLibrary wintun.dll Start ...\n"); HMODULE Wintun = LoadLibraryExW(L"wintun.dll", NULL, LOAD_LIBRARY_SEARCH_APPLICATION_DIR | LOAD_LIBRARY_SEARCH_SYSTEM32); if (!Wintun) { GNB_LOG3(gnb_core->log, GNB_LOG_ID_CORE, "LoadLibrary wintun.dll Failed ...\n"); return NULL; } GNB_LOG3(gnb_core->log, GNB_LOG_ID_CORE, "GetProcAddress wintun.dll Start...\n"); #define X(Name) ((*(FARPROC *)&Name = GetProcAddress(Wintun, #Name)) == NULL) if (X(WintunCreateAdapter) || X(WintunCloseAdapter) || X(WintunOpenAdapter) || X(WintunGetAdapterLUID) || X(WintunGetRunningDriverVersion) || X(WintunDeleteDriver) || X(WintunSetLogger) || X(WintunStartSession) || X(WintunEndSession) || X(WintunGetReadWaitEvent) || X(WintunReceivePacket) || X(WintunReleaseReceivePacket) || X(WintunAllocateSendPacket) || X(WintunSendPacket)) #undef X { DWORD LastError = GetLastError(); FreeLibrary(Wintun); SetLastError(LastError); GNB_LOG3(gnb_core->log, GNB_LOG_ID_CORE, "GetProcAddress wintun.dll Failed...\n"); return NULL; } return Wintun; } typedef struct _gnb_core_wintun_ctx_t{ char if_name[PATH_MAX]; HMODULE drv_module; WINTUN_ADAPTER_HANDLE adapter_handle; WINTUN_SESSION_HANDLE session; HANDLE hQuitEvent; HANDLE hReadEvent; int skip_if_script; }gnb_core_wintun_ctx_t; static int close_tun_wintun(gnb_core_t *gnb_core); static int open_tun_wintun(gnb_core_t *gnb_core); static int release_tun_wintun(gnb_core_t *gnb_core); #define MAX_KEY_LENGTH 255 int init_tun_wintun(gnb_core_t *gnb_core){ gnb_core_wintun_ctx_t *tun_wintun_ctx = (gnb_core_wintun_ctx_t *)malloc(sizeof(gnb_core_wintun_ctx_t)); memset(tun_wintun_ctx, 0, sizeof(gnb_core_wintun_ctx_t)); tun_wintun_ctx->skip_if_script = 0; GNB_LOG3(gnb_core->log, GNB_LOG_ID_CORE, "Notes: gnb_drv_wintun.c is a Third party module; technical support: https://www.github.com/wuqiong\n"); HMODULE module = InitializeWintun(gnb_core); if(NULL == module) { GNB_LOG3(gnb_core->log, GNB_LOG_ID_CORE, "InitializeWintun failed!\n"); WintunDeleteDriver(); return -1; } GNB_LOG3(gnb_core->log, GNB_LOG_ID_CORE, "InitializeWintun success...\n"); HANDLE quit_event = CreateEventW(NULL, TRUE, FALSE, NULL); if (!quit_event) { GNB_LOG3(gnb_core->log, GNB_LOG_ID_CORE, "Failed to create quitevent!\n"); WintunDeleteDriver(); return -2; } tun_wintun_ctx->hQuitEvent = quit_event; tun_wintun_ctx->drv_module = module; gnb_core->platform_ctx = tun_wintun_ctx; snprintf(tun_wintun_ctx->if_name, PATH_MAX, "%s", "P2PNet"); if ( tun_wintun_ctx->if_name && 0 != strncmp(gnb_core->ifname,tun_wintun_ctx->if_name,256) ) { snprintf(gnb_core->ifname, 256, "%s", tun_wintun_ctx->if_name); } if(gnb_core->if_device_string!=NULL) { snprintf(gnb_core->if_device_string, 256, "%s", "P2PNet Device"); } return 0; } static void if_up(gnb_core_t *gnb_core){ char bin_path[PATH_MAX+NAME_MAX]; char bin_path_q[PATH_MAX+NAME_MAX]; char map_path_q[PATH_MAX+NAME_MAX]; gnb_core_wintun_ctx_t *tun_wintun_ctx = gnb_core->platform_ctx; strncpy(gnb_core->ctl_block->conf_zone->conf_st.ifname, tun_wintun_ctx->if_name, NAME_MAX); snprintf(bin_path, PATH_MAX+NAME_MAX, "%s\\gnb_es.exe", gnb_core->ctl_block->conf_zone->conf_st.binary_dir); snprintf(bin_path_q, PATH_MAX+NAME_MAX, "\"%s\\gnb_es.exe\"", gnb_core->ctl_block->conf_zone->conf_st.binary_dir); snprintf(map_path_q, PATH_MAX+NAME_MAX, "\"%s\"", gnb_core->ctl_block->conf_zone->conf_st.map_file); gnb_arg_list_t *arg_list; arg_list = gnb_arg_list_init(32); gnb_arg_append(arg_list, bin_path_q); gnb_arg_append(arg_list, "-b"); gnb_arg_append(arg_list, map_path_q); gnb_arg_append(arg_list, "--if-up"); gnb_exec(bin_path, gnb_core->ctl_block->conf_zone->conf_st.binary_dir, arg_list, GNB_EXEC_BACKGROUND|GNB_EXEC_WAIT); gnb_arg_list_release(arg_list); } static void if_down(gnb_core_t *gnb_core){ gnb_core_wintun_ctx_t *tun_wintun_ctx = gnb_core->platform_ctx; char bin_path[PATH_MAX+NAME_MAX]; char bin_path_q[PATH_MAX+NAME_MAX]; char map_path_q[PATH_MAX+NAME_MAX]; snprintf(bin_path, PATH_MAX+NAME_MAX, "%s\\gnb_es.exe", gnb_core->ctl_block->conf_zone->conf_st.binary_dir); snprintf(bin_path_q, PATH_MAX+NAME_MAX, "\"%s\\gnb_es.exe\"", gnb_core->ctl_block->conf_zone->conf_st.binary_dir); snprintf(map_path_q, PATH_MAX+NAME_MAX, "\"%s\"", gnb_core->ctl_block->conf_zone->conf_st.map_file); gnb_arg_list_t *arg_list; arg_list = gnb_arg_list_init(32); gnb_arg_append(arg_list, bin_path_q); gnb_arg_append(arg_list, "-b"); gnb_arg_append(arg_list, map_path_q); gnb_arg_append(arg_list, "--if-down"); gnb_exec(bin_path, gnb_core->ctl_block->conf_zone->conf_st.binary_dir, arg_list, GNB_EXEC_BACKGROUND|GNB_EXEC_WAIT); gnb_arg_list_release(arg_list); } static int ntod(uint32_t mask){ int i, n = 0; int bits = sizeof(uint32_t) * 8; for (i = bits - 1; i >= 0; i--) { if (mask & (0x01 << i)) n++; } return n; } static int set_addr4(gnb_core_t *gnb_core){ gnb_core_wintun_ctx_t *tun_wintun_ctx = gnb_core->platform_ctx; DWORD dwRetVal = 0; DWORD dwSize = 0; unsigned long status = 0; DWORD lastError = 0; SOCKADDR_IN localAddress; MIB_UNICASTIPADDRESS_ROW ipRow; InitializeUnicastIpAddressEntry( &ipRow ); WintunGetAdapterLUID(tun_wintun_ctx->adapter_handle, &ipRow.InterfaceLuid); ipRow.Address.si_family = AF_INET; ipRow.OnLinkPrefixLength = (UINT8)ntod( gnb_core->local_node->tun_netmask_addr4.s_addr ); InetPton(AF_INET, GNB_ADDR4STR_PLAINTEXT1(&gnb_core->local_node->tun_addr4), &ipRow.Address.Ipv4.sin_addr); status = DeleteUnicastIpAddressEntry(&ipRow); status = CreateUnicastIpAddressEntry(&ipRow); if (status != ERROR_SUCCESS && status != ERROR_OBJECT_ALREADY_EXISTS) { GNB_LOG3(gnb_core->log, GNB_LOG_ID_CORE, "Failed to set IPv4 address: %s\n", GNB_ADDR4STR_PLAINTEXT1(&gnb_core->local_node->tun_addr4)); return -3; } GNB_LOG3(gnb_core->log, GNB_LOG_ID_CORE, "Success to set IPv4 address: %s\n", GNB_ADDR4STR_PLAINTEXT1(&gnb_core->local_node->tun_addr4)); return 0; } static int set_addr6(gnb_core_t *gnb_core){ gnb_core_wintun_ctx_t *tun_wintun_ctx = gnb_core->platform_ctx; DWORD dwRetVal = 0; DWORD dwSize = 0; unsigned long status = 0; DWORD lastError = 0; SOCKADDR_IN localAddress; MIB_UNICASTIPADDRESS_ROW ipRow; InitializeUnicastIpAddressEntry( &ipRow ); WintunGetAdapterLUID(tun_wintun_ctx->adapter_handle, &ipRow.InterfaceLuid); ipRow.Address.si_family = AF_INET6; ipRow.OnLinkPrefixLength = 96; InetPton(AF_INET6, GNB_ADDR6STR_PLAINTEXT1(&gnb_core->local_node->tun_ipv6_addr), &ipRow.Address.Ipv6.sin6_addr); status = DeleteUnicastIpAddressEntry(&ipRow); status = CreateUnicastIpAddressEntry(&ipRow); if (status != ERROR_SUCCESS && status != ERROR_OBJECT_ALREADY_EXISTS) { GNB_LOG3(gnb_core->log, GNB_LOG_ID_CORE, "Failed to set IPv6 address: %s\n", GNB_ADDR6STR_PLAINTEXT1(&gnb_core->local_node->tun_ipv6_addr)); return -3; } GNB_LOG3(gnb_core->log, GNB_LOG_ID_CORE, "Success to set IPv6 address: %s\n", GNB_ADDR6STR_PLAINTEXT1(&gnb_core->local_node->tun_ipv6_addr)); return 0; } static int open_tun_wintun(gnb_core_t *gnb_core){ gnb_core_wintun_ctx_t *tun_wintun_ctx = gnb_core->platform_ctx; int ret; DWORD LastError; if ( NULL != tun_wintun_ctx->adapter_handle ) { GNB_LOG3(gnb_core->log, GNB_LOG_ID_CORE, "Wintun Adapter Exist!\n"); return -1; } GNB_LOG3(gnb_core->log, GNB_LOG_ID_CORE, "WintunCreateAdapter Start...\n"); struct in_addr addr4 = gnb_core->local_node->tun_addr4; GUID Guid = { 0xdeadbabe, 0xcafe, 0xbeef, { 0x01, 0x23, 0x45, 0x67, addr4.S_un.S_un_b.s_b1, addr4.S_un.S_un_b.s_b2, addr4.S_un.S_un_b.s_b3, addr4.S_un.S_un_b.s_b4 } }; //WINTUN_ADAPTER_HANDLE Adapter = WintunCreateAdapter(tun_wintun_ctx->tap_file_name, tun_wintun_ctx->if_name, &Guid); const size_t cSize = strlen(tun_wintun_ctx->if_name) + 1; wchar_t w_if_name[cSize]; mbstowcs (w_if_name, tun_wintun_ctx->if_name, cSize); WINTUN_ADAPTER_HANDLE Adapter = NULL; int try_count = 2; while (NULL == Adapter && try_count > 0) { Adapter = WintunCreateAdapter(w_if_name, WINTUN_POOL_NAME, &Guid); try_count--; } if (NULL == Adapter) { DWORD lastErr = GetLastError(); if( lastErr == ERROR_OBJECT_ALREADY_EXISTS) { GNB_LOG3(gnb_core->log, GNB_LOG_ID_CORE, "WintunCreateAdapter Failed! already exist!\n"); return -1; } else { GNB_LOG3(gnb_core->log, GNB_LOG_ID_CORE, "WintunCreateAdapter Failed: %ld\n", lastErr); return -2; } } GNB_LOG3(gnb_core->log, GNB_LOG_ID_CORE, "WintunCreateAdapter Success...\n"); tun_wintun_ctx->adapter_handle = Adapter; DWORD status4 = set_addr4(gnb_core); if(0 != status4) { WintunCloseAdapter(tun_wintun_ctx->adapter_handle); tun_wintun_ctx->adapter_handle = NULL; return status4; } DWORD status6 = set_addr6(gnb_core); if(0 != status6) { WintunCloseAdapter(tun_wintun_ctx->adapter_handle); tun_wintun_ctx->adapter_handle = NULL; return status6; } WINTUN_SESSION_HANDLE Session = WintunStartSession(tun_wintun_ctx->adapter_handle, WINTUN_RING_CAPACITY); if (!Session) { GNB_LOG3(gnb_core->log, GNB_LOG_ID_CORE, "Failed to WintunStartSession!\n"); WintunCloseAdapter(tun_wintun_ctx->adapter_handle); tun_wintun_ctx->adapter_handle = NULL; return -4; } GNB_LOG3(gnb_core->log, GNB_LOG_ID_CORE, "Success to WintunStartSession!\n"); tun_wintun_ctx->session = Session; tun_wintun_ctx->hReadEvent = WintunGetReadWaitEvent(Session); if ( !tun_wintun_ctx->skip_if_script ) { if_up(gnb_core); } return 0; } static int read_tun_wintun(gnb_core_t *gnb_core, void *buf, size_t buf_size){ gnb_core_wintun_ctx_t *tun_wintun_ctx = gnb_core->platform_ctx; WINTUN_SESSION_HANDLE session = (WINTUN_SESSION_HANDLE)tun_wintun_ctx->session; HANDLE WaitHandles[] = { tun_wintun_ctx->hReadEvent, tun_wintun_ctx->hQuitEvent }; DWORD packet_size; BYTE *packet = WintunReceivePacket(session, &packet_size); if(NULL != packet){ size_t real_size = (packet_size > buf_size)?buf_size:packet_size; memcpy(buf, packet, real_size); WintunReleaseReceivePacket(session, packet); GNB_LOG3(gnb_core->log, GNB_LOG_ID_CORE, "read_tun_wintun bufsize:%d, real WintunReceivePacket size:%d!\n", buf_size, packet_size); return real_size; }else{ DWORD LastError = GetLastError(); switch (LastError ) { case ERROR_NO_MORE_ITEMS: GNB_LOG3(gnb_core->log, GNB_LOG_ID_CORE, "read_tun_wintun Packet read ERROR_NO_MORE_ITEMS:%ld!\n", LastError); if (WaitForMultipleObjects(_countof(WaitHandles), WaitHandles, FALSE, INFINITE) == WAIT_OBJECT_0){ return ERROR_SUCCESS; } break; default: GNB_LOG3(gnb_core->log, GNB_LOG_ID_CORE, "read_tun_wintun Packet read failed:%ld!\n", LastError); return LastError; } } return ERROR_SUCCESS; } static int write_tun_wintun(gnb_core_t *gnb_core, void *buf, size_t buf_size){ gnb_core_wintun_ctx_t *tun_wintun_ctx = gnb_core->platform_ctx; WINTUN_SESSION_HANDLE session = (WINTUN_SESSION_HANDLE)tun_wintun_ctx->session; BYTE *Packet = WintunAllocateSendPacket(session, buf_size); memcpy(Packet, buf, buf_size); DWORD LastError = GetLastError(); if (NULL != Packet) { WintunSendPacket(session, Packet); GNB_LOG3(gnb_core->log, GNB_LOG_ID_CORE, "write_tun_wintun WintunAllocateSendPacket size:%d!\n", buf_size); return 0; } else if (LastError != ERROR_BUFFER_OVERFLOW) { GNB_LOG3(gnb_core->log, GNB_LOG_ID_CORE, "write_tun_wintun WintunAllocateSendPacket size:%d, Packet write failed!\n", buf_size); return 0; } else { return 0; } } static int close_tun_wintun(gnb_core_t *gnb_core){ gnb_core->loop_flag = 0; gnb_core_wintun_ctx_t *tun_wintun_ctx = gnb_core->platform_ctx; if ( !tun_wintun_ctx->skip_if_script ) { if_down(gnb_core); } if(NULL != tun_wintun_ctx->hReadEvent) { SetEvent(tun_wintun_ctx->hReadEvent); tun_wintun_ctx->hReadEvent = NULL; } if(NULL != tun_wintun_ctx->hQuitEvent) { SetEvent(tun_wintun_ctx->hQuitEvent); tun_wintun_ctx->hQuitEvent = NULL; } if(NULL != tun_wintun_ctx->session) { WintunEndSession(tun_wintun_ctx->session); GNB_LOG3(gnb_core->log, GNB_LOG_ID_CORE, "Close Tun, WintunEndSession!\n"); tun_wintun_ctx->session = NULL; } if(NULL != tun_wintun_ctx->adapter_handle) { WintunCloseAdapter(tun_wintun_ctx->adapter_handle); GNB_LOG3(gnb_core->log, GNB_LOG_ID_CORE, "Close Tun, WintunCloseAdapter!\n"); tun_wintun_ctx->adapter_handle = NULL; } return release_tun_wintun(gnb_core); } static int release_tun_wintun(gnb_core_t *gnb_core){ gnb_core_wintun_ctx_t *tun_wintun_ctx = gnb_core->platform_ctx; if (NULL != tun_wintun_ctx) { if (NULL != tun_wintun_ctx->drv_module) { FreeLibrary(tun_wintun_ctx->drv_module); tun_wintun_ctx->drv_module = NULL; GNB_LOG3(gnb_core->log, GNB_LOG_ID_CORE, "Release Tun, FreeLibrary!\n"); } free(gnb_core->platform_ctx); gnb_core->platform_ctx = NULL; } return 0; } gnb_tun_drv_t gnb_tun_drv_wintun = { init_tun_wintun, open_tun_wintun, read_tun_wintun, write_tun_wintun, close_tun_wintun, release_tun_wintun }; opengnb-ver1.6.0.a/src/mingw/gnb_res.rc000077500000000000000000000000311500454252100177520ustar00rootroot000000000000001 24 "gnb.exe.manifest" opengnb-ver1.6.0.a/src/mingw/windows_platform.c000077500000000000000000000056541500454252100215670ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 #include #include #include #include "gnb_exec.h" #include "gnb_arg_list.h" int gnb_get_pid(){ int pid; pid = GetCurrentProcessId(); return pid; } void gnb_set_env(const char *name, const char *value){ _putenv_s(name, value); } int gnb_exec(char *app_filename, char *current_path, gnb_arg_list_t *gnb_arg_list, int flag){ int rc; wchar_t app_filename_w[PATH_MAX+NAME_MAX]; wchar_t gnb_arg_string_w[PATH_MAX+NAME_MAX]; wchar_t current_path_w[PATH_MAX+NAME_MAX]; STARTUPINFOW si; PROCESS_INFORMATION pi = {0}; DWORD creation_flags; ZeroMemory(&si,sizeof(si)); si.cb = sizeof(si); char gnb_arg_string[GNB_ARG_STRING_MAX_SIZE]; rc = gnb_arg_list_to_string(gnb_arg_list, gnb_arg_string, GNB_ARG_STRING_MAX_SIZE); if ( flag & GNB_EXEC_BACKGROUND ) { si.wShowWindow = SW_HIDE; si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES; creation_flags = CREATE_NO_WINDOW; } else { si.dwFlags = STARTF_USESHOWWINDOW; si.wShowWindow = SW_SHOW; creation_flags = CREATE_NEW_CONSOLE; } memset(app_filename_w, 0, PATH_MAX+NAME_MAX); MultiByteToWideChar(CP_ACP, 0, app_filename, -1, app_filename_w, PATH_MAX+NAME_MAX); memset(current_path_w, 0, PATH_MAX+NAME_MAX); MultiByteToWideChar(CP_ACP, 0, current_path, -1, current_path_w, PATH_MAX+NAME_MAX); memset(gnb_arg_string_w, 0, PATH_MAX+NAME_MAX); MultiByteToWideChar(CP_ACP, 0, gnb_arg_string, -1, gnb_arg_string_w, PATH_MAX+NAME_MAX); rc = CreateProcessW(app_filename_w, gnb_arg_string_w, NULL,NULL,TRUE, creation_flags, NULL, current_path_w, &si,&pi); if ( !rc ) { return -1; } if ( flag & GNB_EXEC_WAIT ) { WaitForSingleObject(pi.hProcess, INFINITE); DWORD exitcode; rc = GetExitCodeProcess(pi.hProcess, &exitcode); } if ( pi.hProcess ) { CloseHandle(pi.hProcess); pi.hProcess = NULL; } if ( pi.hThread ) { CloseHandle(pi.hThread); pi.hThread = NULL; } return pi.dwProcessId; } int gnb_kill(DWORD pid){ HANDLE hProcess=OpenProcess(PROCESS_TERMINATE,FALSE, pid); TerminateProcess(hProcess, 0); return 0; } opengnb-ver1.6.0.a/src/openbsd/000077500000000000000000000000001500454252100163215ustar00rootroot00000000000000opengnb-ver1.6.0.a/src/openbsd/gnb_drv_openbsd.c000077500000000000000000000220011500454252100216160ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "gnb.h" #include "gnb_tun_drv.h" #include "gnb_payload16.h" void bind_socket_if(gnb_core_t *gnb_core){ if ( '\0' == gnb_core->conf->socket_ifname[0] ) { return; } int i; for ( i=0; i < gnb_core->conf->udp6_socket_num; i++ ) { setsockopt(gnb_core->udp_ipv6_sockets[i], SOL_SOCKET,IP_RECVIF, gnb_core->conf->socket_ifname, strlen(gnb_core->conf->socket_ifname)); } for ( i=0; i < gnb_core->conf->udp4_socket_num; i++ ) { setsockopt(gnb_core->udp_ipv4_sockets[i], SOL_SOCKET,IP_RECVIF, gnb_core->conf->socket_ifname, strlen(gnb_core->conf->socket_ifname)); } } static void if_up_script(gnb_core_t *gnb_core){ int ret; char cmd[1024]; snprintf(cmd,1024,"\"%s/scripts/%s\" > /dev/null 2>&1",gnb_core->conf->conf_dir,"if_up_openbsd.sh"); ret = system(cmd); if ( -1==ret || 0 ==ret ) { return; } return; } static void if_down_script(gnb_core_t *gnb_core){ int ret; char cmd[1024]; snprintf(cmd,1024,"\"%s/scripts/%s\" > /dev/null 2>&1",gnb_core->conf->conf_dir,"if_down_openbsd.sh"); ret = system(cmd); if ( -1==ret || 0 ==ret ) { return; } return; } /* set_route4的作用是 创建一条路由,以 tun ip 为 10.1.0.15 的local node为例: route -n add -net 10.1.0.0 -netmask 255.255.255.0 10.1.0.15 */ static void set_route4(gnb_core_t *gnb_core){ struct{ struct rt_msghdr hdr; struct sockaddr_in dst; struct sockaddr_in gateway; struct sockaddr_in mask; }rtmsg; uint32_t network_u32; int s; ssize_t wlen; //算出 节点的 ipv4 network network_u32 = gnb_core->local_node->tun_netmask_addr4.s_addr & gnb_core->local_node->tun_addr4.s_addr; s = socket(PF_ROUTE, SOCK_RAW, 0); if (s < 0) { perror("socket\n"); return; } shutdown(s, SHUT_RD); bzero(&rtmsg, sizeof(rtmsg)); rtmsg.hdr.rtm_type = RTM_ADD; rtmsg.hdr.rtm_version = RTM_VERSION; rtmsg.hdr.rtm_addrs = 0; rtmsg.hdr.rtm_addrs |= RTA_DST; rtmsg.hdr.rtm_addrs |= RTA_GATEWAY; rtmsg.hdr.rtm_addrs |= RTA_NETMASK; rtmsg.hdr.rtm_flags = RTF_STATIC; rtmsg.hdr.rtm_flags |= RTF_GATEWAY; rtmsg.hdr.rtm_flags |= RTF_GATEWAY; rtmsg.dst.sin_len = sizeof(rtmsg.dst); rtmsg.dst.sin_family = AF_INET; rtmsg.dst.sin_addr.s_addr = network_u32; rtmsg.mask.sin_len = sizeof(rtmsg.mask); rtmsg.mask.sin_family = AF_INET; rtmsg.mask.sin_addr.s_addr = gnb_core->local_node->tun_netmask_addr4.s_addr; rtmsg.gateway.sin_len = sizeof(rtmsg.gateway); rtmsg.gateway.sin_family = AF_INET; rtmsg.gateway.sin_addr.s_addr = gnb_core->local_node->tun_addr4.s_addr; rtmsg.hdr.rtm_msglen = sizeof(rtmsg); wlen = write(s, &rtmsg, sizeof(rtmsg)); if ( -1==wlen ) { perror("#set_route4 write"); return; } return; } static void setifmtu(char *if_name,int mtu) { int socket_fd; struct ifreq ifr; memset(&ifr,0,sizeof(struct ifreq)); strncpy(ifr.ifr_name, if_name, IFNAMSIZ); ifr.ifr_mtu = mtu; if ((socket_fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { perror("socket "); } int ret = ioctl(socket_fd, SIOCSIFMTU, &ifr); if (-1==ret) { perror("ioctl"); } close(socket_fd); } static int set_addr4(char *if_name, char *ip, char *netmask) { struct addrinfo *srcres, *dstres, *netmaskres; struct ifaliasreq in_addreq; memset(&in_addreq, 0, sizeof(in_addreq)); getaddrinfo(ip, NULL, NULL, &srcres); getaddrinfo(ip, NULL, NULL, &dstres); getaddrinfo(netmask, NULL, NULL, &netmaskres); strncpy(in_addreq.ifra_name, if_name, IFNAMSIZ); memcpy(&in_addreq.ifra_addr, srcres->ai_addr, srcres->ai_addr->sa_len); memcpy(&in_addreq.ifra_dstaddr, dstres->ai_addr, dstres->ai_addr->sa_len); memcpy(&in_addreq.ifra_mask, netmaskres->ai_addr, netmaskres->ai_addr->sa_len); freeaddrinfo(srcres); freeaddrinfo(dstres); freeaddrinfo(netmaskres); int socket_fd; if ( (socket_fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) { perror("socket "); return -1; } int ret = ioctl(socket_fd, SIOCAIFADDR, &in_addreq); if (-1==ret) { perror("ioctl"); } return 0; } static int set_addr6(char *if_name, char *ip, char *netmask) { //不要设置 in6_addreq.ifra_dstaddr 成员, ioctl 会提示参数不正确 struct in6_aliasreq in6_addreq = { { 0 }, { 0 }, { 0 }, { 0 }, 0, { 0, 0, ND6_INFINITE_LIFETIME, ND6_INFINITE_LIFETIME } }; struct addrinfo *srcres, *netmaskres; struct addrinfo hints; bzero(&hints, sizeof(struct addrinfo)); hints.ai_family = AF_INET6; getaddrinfo(ip, NULL, &hints, &srcres); getaddrinfo(netmask, NULL, &hints, &netmaskres); strncpy(in6_addreq.ifra_name, if_name, IFNAMSIZ); memcpy(&in6_addreq.ifra_addr, srcres->ai_addr, srcres->ai_addr->sa_len); memcpy(&in6_addreq.ifra_prefixmask, netmaskres->ai_addr, netmaskres->ai_addr->sa_len); freeaddrinfo(srcres); freeaddrinfo(netmaskres); int socket_fd; if ( (socket_fd = socket(AF_INET6, SOCK_DGRAM, 0)) < 0 ) { perror("socket "); return -1; } int ret = ioctl(socket_fd, SIOCAIFADDR_IN6, &in6_addreq); if (-1==ret) { perror("ioctl"); } close(socket_fd); return ret; } int init_tun_openbsd(gnb_core_t *gnb_core){ gnb_core->tun_fd = -1; return 0; } static int open_tun_openbsd(gnb_core_t *gnb_core){ if ( -1 != gnb_core->tun_fd ) { return -1; } char name[PATH_MAX]; int t = 0; snprintf(name, PATH_MAX, "/dev/%s",gnb_core->ifname); gnb_core->tun_fd = open(name, O_RDWR); if (-1==gnb_core->tun_fd) { perror("open"); exit(1); } int flags; flags = fcntl(gnb_core->tun_fd, F_GETFD); flags |= FD_CLOEXEC; fcntl(gnb_core->tun_fd, F_SETFD, flags); set_addr4(gnb_core->ifname, GNB_ADDR4STR1(&gnb_core->local_node->tun_addr4), GNB_ADDR4STR2(&gnb_core->local_node->tun_netmask_addr4)); set_addr6(gnb_core->ifname, GNB_ADDR6STR1(&gnb_core->local_node->tun_ipv6_addr), "FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:0000:0000"); set_route4(gnb_core); setifmtu(gnb_core->ifname, gnb_core->conf->mtu); if_up_script(gnb_core); return 0; } static int read_tun_openbsd(gnb_core_t *gnb_core, void *buf, size_t buf_size){ ssize_t rlen; u_int32_t type; struct iovec iv[2]; struct ip *iph; iph = (struct ip *) buf; if (iph->ip_v == 6) { type = htonl(AF_INET6); } else { type = htonl(AF_INET); } iv[0].iov_base = (char *)&type; iv[0].iov_len = sizeof (type); iv[1].iov_base = buf; iv[1].iov_len = buf_size; rlen = readv(gnb_core->tun_fd, iv, 2); if (-1==rlen) { return rlen; } if ( rlen - sizeof(u_int32_t) <=0 ) { return -1; } return rlen - sizeof(u_int32_t); } static int write_tun_openbsd(gnb_core_t *gnb_core, void *buf, size_t buf_size){ u_int32_t type; struct iovec iv[2]; struct ip *iph; iph = (struct ip *) buf; if (iph->ip_v == 6) { type = htonl(AF_INET6); } else { type = htonl(AF_INET); } iv[0].iov_base = (char *)&type; iv[0].iov_len = sizeof (type); iv[1].iov_base = buf; iv[1].iov_len = buf_size; writev(gnb_core->tun_fd, iv, 2); return 0; } static int close_tun_openbsd(gnb_core_t *gnb_core){ if_down_script(gnb_core); close(gnb_core->tun_fd); return 0; } static int release_tun_openbsd(gnb_core_t *gnb_core){ return 0; } gnb_tun_drv_t gnb_tun_drv_openbsd = { init_tun_openbsd, open_tun_openbsd, read_tun_openbsd, write_tun_openbsd, close_tun_openbsd, release_tun_openbsd }; opengnb-ver1.6.0.a/src/packet_filter/000077500000000000000000000000001500454252100175035ustar00rootroot00000000000000opengnb-ver1.6.0.a/src/packet_filter/gnb_pf_crypto_arc4.c000077500000000000000000000175411500454252100234260ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 "gnb.h" #include "gnb_payload16.h" #include "gnb_hash32.h" #include "crypto/arc4/arc4.h" #include "gnb_keys.h" #include "protocol/network_protocol.h" typedef struct _gnb_pf_private_ctx_t { int save_time_seed_update_factor; gnb_hash32_map_t *arc4_ctx_map; }gnb_pf_private_ctx_t; gnb_pf_t gnb_pf_crypto_arc4; static void init_arc4_keys(gnb_core_t *gnb_core,gnb_pf_t *pf){ int i; gnb_node_t *node; gnb_pf_private_ctx_t *ctx = pf->private_ctx; ctx->save_time_seed_update_factor = gnb_core->time_seed_update_factor; int num = gnb_core->ctl_block->node_zone->node_num; if ( 0 == num ) { return; } struct arc4_sbox *sbox; for (i=0; i < num; i++) { node = &gnb_core->ctl_block->node_zone->node[i]; gnb_build_crypto_key(gnb_core, node); sbox = GNB_HASH32_UINT64_GET_PTR(ctx->arc4_ctx_map, node->uuid64); if ( NULL == sbox ) { continue; } arc4_init(sbox, node->crypto_key, 64); } } static void pf_init_cb(gnb_core_t *gnb_core, gnb_pf_t *pf){ gnb_pf_private_ctx_t *ctx = (gnb_pf_private_ctx_t*)gnb_heap_alloc(gnb_core->heap,sizeof(gnb_pf_private_ctx_t)); ctx->arc4_ctx_map = gnb_hash32_create(gnb_core->heap,gnb_core->node_nums,gnb_core->node_nums); pf->private_ctx = ctx; int num = gnb_core->ctl_block->node_zone->node_num; if ( 0 == num ) { return; } int i; gnb_node_t *node; struct arc4_sbox *sbox; for (i=0; i < num; i++) { node = &gnb_core->ctl_block->node_zone->node[i]; gnb_build_crypto_key(gnb_core, node); sbox = gnb_heap_alloc(gnb_core->heap, sizeof(struct arc4_sbox)); arc4_init(sbox, node->crypto_key, 64); GNB_HASH32_UINT64_SET(ctx->arc4_ctx_map, node->uuid64, sbox); } GNB_LOG1(gnb_core->log, GNB_LOG_ID_PF, "%s init\n", pf->name); } static void pf_conf_cb(gnb_core_t *gnb_core, gnb_pf_t *pf) { init_arc4_keys(gnb_core,pf); } /* 用dst node 的key 加密 ip frmae for P2P */ static int pf_tun_route_cb(gnb_core_t *gnb_core, gnb_pf_t *pf, gnb_pf_ctx_t *pf_ctx){ gnb_pf_private_ctx_t *ctx = (gnb_pf_private_ctx_t *)pf->private_ctx; if ( ctx->save_time_seed_update_factor != gnb_core->time_seed_update_factor ) { init_arc4_keys(gnb_core,pf); } struct arc4_sbox sbox; if ( NULL==pf_ctx->dst_node ) { return GNB_PF_ERROR; } struct arc4_sbox *sbox_init = (struct arc4_sbox *)GNB_HASH32_UINT64_GET_PTR(ctx->arc4_ctx_map, pf_ctx->dst_uuid64); if ( NULL==sbox_init ) { GNB_LOG3(gnb_core->log, GNB_LOG_ID_PF, "gnb_pf_crypto_arc4 tun_frame node[%llu] miss key\n", pf_ctx->dst_node->uuid64); return GNB_PF_ERROR; } sbox = *sbox_init; arc4_crypt(&sbox, pf_ctx->ip_frame, pf_ctx->ip_frame_size); return pf_ctx->pf_status; } /* 用 src_node 的密钥对 payload 进行解密, 得到来自 src_node 的虚拟网卡的 ip frame, 这些 ip frame 将被写入虚拟网卡 */ static int pf_inet_route_cb(gnb_core_t *gnb_core, gnb_pf_t *pf, gnb_pf_ctx_t *pf_ctx){ gnb_pf_private_ctx_t *ctx = (gnb_pf_private_ctx_t *)pf->private_ctx; if ( ctx->save_time_seed_update_factor != gnb_core->time_seed_update_factor ) { init_arc4_keys(gnb_core,pf); } if ( GNB_PF_FWD_TUN==pf_ctx->pf_fwd ) { struct arc4_sbox *sbox_init = (struct arc4_sbox *)GNB_HASH32_UINT64_GET_PTR(ctx->arc4_ctx_map, pf_ctx->src_uuid64); if ( NULL==sbox_init ) { GNB_LOG3(gnb_core->log, GNB_LOG_ID_PF, "gnb_pf_crypto_arc4 inet_route node[%llu] miss key\n", pf_ctx->src_uuid64); return GNB_PF_ERROR; } struct arc4_sbox sbox = *sbox_init; arc4_crypt(&sbox, pf_ctx->ip_frame, pf_ctx->ip_frame_size); } return pf_ctx->pf_status; } /* 只处理有 GNB_PAYLOAD_SUB_TYPE_IPFRAME_RELAY 标记的 payload payload 发往用下一跳前,用下一跳节点的的密钥加密 payload */ static int pf_chain_relay_cb(gnb_core_t *gnb_core, gnb_pf_t *pf, gnb_pf_ctx_t *pf_ctx){ gnb_pf_private_ctx_t *ctx = (gnb_pf_private_ctx_t *)pf->private_ctx; struct arc4_sbox sbox; if ( !(pf_ctx->fwd_payload->sub_type & GNB_PAYLOAD_SUB_TYPE_IPFRAME_RELAY) ) { return pf_ctx->pf_status; } if ( ctx->save_time_seed_update_factor != gnb_core->time_seed_update_factor ) { init_arc4_keys(gnb_core,pf); } if ( GNB_PF_FWD_INET==pf_ctx->pf_fwd ) { if ( NULL==pf_ctx->fwd_node ) { pf_ctx->pf_status = GNB_PF_NOROUTE; goto finish; } struct arc4_sbox *sbox_init = (struct arc4_sbox *)GNB_HASH32_UINT64_GET_PTR(ctx->arc4_ctx_map, pf_ctx->fwd_node->uuid64); if ( NULL==sbox_init ) { GNB_LOG3(gnb_core->log, GNB_LOG_ID_PF, "gnb_pf_crypto_arc4 pf_inet_frame_cb node[%llu] miss key\n", pf_ctx->fwd_node->uuid64); return GNB_PF_ERROR; } sbox = *sbox_init; arc4_crypt(&sbox, pf_ctx->fwd_payload->data, gnb_payload16_data_len(pf_ctx->fwd_payload)-sizeof(gnb_uuid_t)); } finish: return pf_ctx->pf_status; } /* 只处理有 GNB_PAYLOAD_SUB_TYPE_IPFRAME_RELAY 标记的 payload 用上一跳的 relay 节点(src_fwd_nodeb)的密钥为 payload 解密 */ static int pf_inet_frame_cb(gnb_core_t *gnb_core, gnb_pf_t *pf, gnb_pf_ctx_t *pf_ctx){ gnb_pf_private_ctx_t *ctx = (gnb_pf_private_ctx_t *)pf->private_ctx; struct arc4_sbox sbox; uint16_t payload_size; if ( !(pf_ctx->fwd_payload->sub_type & GNB_PAYLOAD_SUB_TYPE_IPFRAME_RELAY) ) { return pf_ctx->pf_status; } if ( ctx->save_time_seed_update_factor != gnb_core->time_seed_update_factor ) { init_arc4_keys(gnb_core,pf); } payload_size = gnb_payload16_size(pf_ctx->fwd_payload); gnb_uuid_t src_fwd_nodeid; memcpy(&src_fwd_nodeid, ((void *)pf_ctx->fwd_payload + payload_size - sizeof(gnb_uuid_t)), sizeof(gnb_uuid_t)); pf_ctx->src_fwd_uuid64 = gnb_ntohll(src_fwd_nodeid); struct arc4_sbox *sbox_init = (struct arc4_sbox *)GNB_HASH32_UINT64_GET_PTR(ctx->arc4_ctx_map, pf_ctx->src_fwd_uuid64); if ( NULL==sbox_init ) { GNB_LOG3(gnb_core->log, GNB_LOG_ID_PF, "gnb_pf_crypto_arc4 pf_inet_frame_cb node[%llu] miss key\n", pf_ctx->src_fwd_uuid64); return GNB_PF_ERROR; } sbox = *sbox_init; arc4_crypt(&sbox, pf_ctx->fwd_payload->data, gnb_payload16_data_len(pf_ctx->fwd_payload)-sizeof(gnb_uuid_t)); finish: return pf_ctx->pf_status; } static void pf_release_cb(gnb_core_t *gnb_core, gnb_pf_t *pf){ } gnb_pf_t gnb_pf_crypto_arc4 = { .name = "gnb_pf_crypto_arc4", .type = GNB_PF_TYEP_UNSET, .private_ctx = NULL, .pf_init = pf_init_cb, .pf_conf = pf_conf_cb, .pf_tun_frame = NULL, // pf_tun_frame .pf_tun_route = pf_tun_route_cb, // pf_tun_route .pf_tun_fwd = pf_chain_relay_cb, // pf_tun_fwd GNB_PAYLOAD_SUB_TYPE_IPFRAME_RELAY .pf_inet_frame = pf_inet_frame_cb, // pf_inet_frame GNB_PAYLOAD_SUB_TYPE_IPFRAME_RELAY .pf_inet_route = pf_inet_route_cb, // pf_inet_route .pf_inet_fwd = pf_chain_relay_cb, // pf_inet_fwd GNB_PAYLOAD_SUB_TYPE_IPFRAME_RELAY .pf_release = pf_release_cb // pf_release }; opengnb-ver1.6.0.a/src/packet_filter/gnb_pf_crypto_xor.c000077500000000000000000000141221500454252100233750ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 "gnb.h" #include "gnb_payload16.h" #include "protocol/network_protocol.h" #include "gnb_binary.h" typedef struct _gnb_pf_private_ctx_t { int save_time_seed_update_factor; }gnb_pf_private_ctx_t; gnb_pf_t gnb_pf_crypto_xor; static void pf_init_cb(gnb_core_t *gnb_core, gnb_pf_t *pf){ gnb_pf_private_ctx_t *ctx = (gnb_pf_private_ctx_t*)gnb_heap_alloc(gnb_core->heap,sizeof(gnb_pf_private_ctx_t)); pf->private_ctx = ctx; GNB_LOG1(gnb_core->log, GNB_LOG_ID_PF, "%s init\n", pf->name); } static void pf_conf_cb(gnb_core_t *gnb_core, gnb_pf_t *pf) { } /* 用dst node 的key 加密 ip frmae for P2P */ static int pf_tun_route_cb(gnb_core_t *gnb_core, gnb_pf_t *pf, gnb_pf_ctx_t *pf_ctx){ gnb_pf_private_ctx_t *ctx = (gnb_pf_private_ctx_t *)pf->private_ctx; ctx->save_time_seed_update_factor = gnb_core->time_seed_update_factor; if ( NULL==pf_ctx->dst_node ) { return GNB_PF_ERROR; } int i; int j = 0; unsigned char *p = (unsigned char *)pf_ctx->ip_frame; for ( i=0; iip_frame_size; i++ ) { *p = *p ^ pf_ctx->dst_node->crypto_key[j]; p++; j++; if ( j >= 64 ) { j = 0; } } return pf_ctx->pf_status;; } /* 用 src_node 的密钥对 payload 进行解密, 得到来自 src_node 的虚拟网卡的 ip frame, 这些 ip frame 将被写入虚拟网卡 */ static int pf_inet_route_cb(gnb_core_t *gnb_core, gnb_pf_t *pf, gnb_pf_ctx_t *pf_ctx){ gnb_pf_private_ctx_t *ctx = (gnb_pf_private_ctx_t *)pf->private_ctx; ctx->save_time_seed_update_factor = gnb_core->time_seed_update_factor; gnb_node_t *src_node; int i; int j = 0; unsigned char *p = (unsigned char *)pf_ctx->ip_frame; if ( GNB_PF_FWD_TUN==pf_ctx->pf_fwd ) { src_node = pf_ctx->src_node; if ( NULL == src_node ) { return GNB_PF_ERROR; } for ( i=0; iip_frame_size; i++ ) { *p = *p ^ src_node->crypto_key[j]; p++; j++; if ( j >= 64 ) { j = 0; } } } return pf_ctx->pf_status; } /* 只处理有 GNB_PAYLOAD_SUB_TYPE_IPFRAME_RELAY 标记的 payload payload 发往用下一跳前,用下一跳节点的的密钥加密 payload */ static int pf_chain_relay_cb(gnb_core_t *gnb_core, gnb_pf_t *pf, gnb_pf_ctx_t *pf_ctx){ gnb_pf_private_ctx_t *ctx = (gnb_pf_private_ctx_t *)pf->private_ctx; ctx->save_time_seed_update_factor = gnb_core->time_seed_update_factor; int i; int j = 0; unsigned char *p; if ( !(pf_ctx->fwd_payload->sub_type & GNB_PAYLOAD_SUB_TYPE_IPFRAME_RELAY) ) { return pf_ctx->pf_status; } if ( GNB_PF_FWD_INET==pf_ctx->pf_fwd ) { if ( NULL==pf_ctx->fwd_node ) { pf_ctx->pf_status = GNB_PF_NOROUTE; goto finish; } p = (unsigned char *)pf_ctx->fwd_payload->data; for ( i=0; i < (gnb_payload16_data_len(pf_ctx->fwd_payload)-sizeof(gnb_uuid_t)); i++ ) { *p = *p ^ pf_ctx->fwd_node->crypto_key[j]; p++; j++; if ( j >= 64 ) { j = 0; } } pf_ctx->pf_status = GNB_PF_NEXT; } finish: return pf_ctx->pf_status; } /* 只处理有 GNB_PAYLOAD_SUB_TYPE_IPFRAME_RELAY 标记的 payload 用上一跳的 relay 节点(src_fwd_nodeb)的密钥为 payload 解密 */ static int pf_inet_frame_cb(gnb_core_t *gnb_core, gnb_pf_t *pf, gnb_pf_ctx_t *pf_ctx){ gnb_pf_private_ctx_t *ctx = (gnb_pf_private_ctx_t *)pf->private_ctx; ctx->save_time_seed_update_factor = gnb_core->time_seed_update_factor; uint16_t payload_size; if ( !(pf_ctx->fwd_payload->sub_type & GNB_PAYLOAD_SUB_TYPE_IPFRAME_RELAY) ) { return pf_ctx->pf_status; } payload_size = gnb_payload16_size(pf_ctx->fwd_payload); gnb_uuid_t src_fwd_nodeid; memcpy(&src_fwd_nodeid, ((void *)pf_ctx->fwd_payload + payload_size - sizeof(gnb_uuid_t)), sizeof(gnb_uuid_t)); pf_ctx->src_fwd_uuid64 = gnb_ntohll(src_fwd_nodeid); pf_ctx->src_fwd_node = GNB_HASH32_UINT64_GET_PTR(gnb_core->uuid_node_map, pf_ctx->src_fwd_uuid64); if ( NULL==pf_ctx->src_fwd_node ) { pf_ctx->pf_status = GNB_PF_NOROUTE; goto finish; } int i; int j = 0; unsigned char *p; p = (unsigned char *)pf_ctx->fwd_payload->data; for ( i=0; i < (gnb_payload16_data_len(pf_ctx->fwd_payload)-sizeof(gnb_uuid_t)); i++ ) { *p = *p ^ pf_ctx->src_fwd_node->crypto_key[j]; p++; j++; if ( j >= 64 ) { j = 0; } } goto finish; finish: return pf_ctx->pf_status; } static void pf_release_cb(gnb_core_t *gnb_core, gnb_pf_t *pf){ } gnb_pf_t gnb_pf_crypto_xor = { .name = "gnb_pf_crypto_xor", .type = GNB_PF_TYEP_UNSET, .private_ctx = NULL, .pf_init = pf_init_cb, .pf_conf = pf_conf_cb, .pf_tun_frame = NULL, // pf_tun_frame .pf_tun_route = pf_tun_route_cb, // pf_tun_route .pf_tun_fwd = pf_chain_relay_cb, // pf_tun_fwd GNB_PAYLOAD_SUB_TYPE_IPFRAME_RELAY .pf_inet_frame = pf_inet_frame_cb, // pf_inet_frame GNB_PAYLOAD_SUB_TYPE_IPFRAME_RELAY .pf_inet_route = pf_inet_route_cb, // pf_inet_route .pf_inet_fwd = pf_chain_relay_cb, // pf_inet_fwd GNB_PAYLOAD_SUB_TYPE_IPFRAME_RELAY .pf_release = pf_release_cb // pf_release }; opengnb-ver1.6.0.a/src/packet_filter/gnb_pf_dump.c000077500000000000000000000144611500454252100221400ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 "gnb.h" #include "gnb_pf.h" #include "gnb_payload16.h" #include "protocol/network_protocol.h" #ifdef __UNIX_LIKE_OS__ #include #include #include #endif #ifdef _WIN32 #undef _WIN32_WINNT #define _WIN32_WINNT 0x0600 #include #include #endif gnb_pf_t gnb_pf_dump; static void pf_init_cb(gnb_core_t *gnb_core, gnb_pf_t *pf){ GNB_LOG1(gnb_core->log, GNB_LOG_ID_PF, "%s init\n", pf->name); } static void pf_conf_cb(gnb_core_t *gnb_core, gnb_pf_t *pf){ } static int pf_tun_frame_cb(gnb_core_t *gnb_core, gnb_pf_t *pf, gnb_pf_ctx_t *pf_ctx){ char src_ipv4_string[INET_ADDRSTRLEN]; char dst_ipv4_string[INET_ADDRSTRLEN]; char src_ipv6_string[INET6_ADDRSTRLEN]; char dst_ipv6_string[INET6_ADDRSTRLEN]; struct iphdr *ip_frame_head = (struct iphdr* )(pf_ctx->fwd_payload->data + gnb_core->tun_payload_offset); struct ip6_hdr *ip6_frame_head = (struct ip6_hdr*)(pf_ctx->fwd_payload->data + gnb_core->tun_payload_offset); static uint64_t seq = 0; seq++; if ( 0x4 != ip_frame_head->version && 0x6 != ip_frame_head->version ) { GNB_LOG3(gnb_core->log,GNB_LOG_ID_PF,"dump pf_tun_frame_cb 0x4!=ip_frame_head->version 0x6!=ip_frame_head->version version[%x]\n", ip_frame_head->version); return pf_ctx->pf_status; } if ( 0x4 == ip_frame_head->version ) { inet_ntop(AF_INET, &ip_frame_head->saddr, src_ipv4_string, INET_ADDRSTRLEN); inet_ntop(AF_INET, &ip_frame_head->daddr, dst_ipv4_string, INET_ADDRSTRLEN); GNB_LOG3(gnb_core->log,GNB_LOG_ID_PF,"tun seq[%"PRIu64"]%s > %s out:%u\n",seq, src_ipv4_string, dst_ipv4_string, gnb_payload16_size(pf_ctx->fwd_payload)); return pf_ctx->pf_status; } uint32_t src_ip_int; uint32_t dst_ip_int; if ( 0x6 == ip_frame_head->version ) { src_ip_int = ip6_frame_head->ip6_src.__in6_u.__u6_addr32[3]; dst_ip_int = ip6_frame_head->ip6_dst.__in6_u.__u6_addr32[3]; inet_ntop(AF_INET, &src_ip_int, src_ipv4_string, INET_ADDRSTRLEN); inet_ntop(AF_INET, &dst_ip_int, dst_ipv4_string, INET_ADDRSTRLEN); inet_ntop(AF_INET6, &ip6_frame_head->ip6_src, src_ipv6_string, INET6_ADDRSTRLEN); inet_ntop(AF_INET6, &ip6_frame_head->ip6_dst, dst_ipv6_string, INET6_ADDRSTRLEN); GNB_LOG3(gnb_core->log,GNB_LOG_ID_PF,"tun seq[%"PRIu64"][%s][%s] > [%s][%s] out:%u\n", seq, src_ipv6_string, src_ipv4_string, dst_ipv6_string, dst_ipv4_string, gnb_payload16_size(pf_ctx->fwd_payload)); } return pf_ctx->pf_status; } static int pf_tun_route_cb(gnb_core_t *gnb_core, gnb_pf_t *pf, gnb_pf_ctx_t *pf_ctx){ return pf_ctx->pf_status; } static int pf_tun_fwd_cb(gnb_core_t *gnb_core, gnb_pf_t *pf, gnb_pf_ctx_t *pf_ctx){ return pf_ctx->pf_status; } static int pf_inet_frame_cb(gnb_core_t *gnb_core, gnb_pf_t *pf, gnb_pf_ctx_t *pf_ctx){ return pf_ctx->pf_status; } static int pf_inet_route_cb(gnb_core_t *gnb_core, gnb_pf_t *pf, gnb_pf_ctx_t *pf_ctx){ return pf_ctx->pf_status; } static int pf_inet_fwd_cb(gnb_core_t *gnb_core, gnb_pf_t *pf, gnb_pf_ctx_t *pf_ctx){ char src_ipv4_string[INET_ADDRSTRLEN]; char dst_ipv4_string[INET_ADDRSTRLEN]; char src_ipv6_string[INET6_ADDRSTRLEN]; char dst_ipv6_string[INET6_ADDRSTRLEN]; struct iphdr *ip_frame_head = (struct iphdr *)pf_ctx->ip_frame; struct ip6_hdr *ip6_frame_head = (struct ip6_hdr*)pf_ctx->ip_frame; static uint64_t seq = 0; seq++; if ( gnb_core->local_node->uuid64 != pf_ctx->dst_uuid64 ) { GNB_LOG3(gnb_core->log,GNB_LOG_ID_PF,"inet dump[%"PRIu64"] [%llu] < [%llu] in:%u\n",seq, pf_ctx->dst_uuid64, pf_ctx->src_uuid64, gnb_payload16_size(pf_ctx->fwd_payload)); return pf_ctx->pf_status; } if ( 0x4 != ip_frame_head->version && 0x6 != ip_frame_head->version ) { GNB_LOG3(gnb_core->log,GNB_LOG_ID_PF,"dump pf_inet_fwd_cb 0x4!=ip_frame_head->version 0x6!=ip_frame_head->version version[%x]\n", ip_frame_head->version); return pf_ctx->pf_status; } if ( 0x4 == ip_frame_head->version ) { inet_ntop(AF_INET, &ip_frame_head->saddr, src_ipv4_string, INET_ADDRSTRLEN); inet_ntop(AF_INET, &ip_frame_head->daddr, dst_ipv4_string, INET_ADDRSTRLEN); GNB_LOG3(gnb_core->log,GNB_LOG_ID_PF,"inet dump[%"PRIu64"] [%llu]%s < [%llu]%s in:%u\n",seq, pf_ctx->dst_uuid64,dst_ipv4_string, pf_ctx->src_uuid64,src_ipv4_string, gnb_payload16_size(pf_ctx->fwd_payload)); return pf_ctx->pf_status; } if ( 0x6 == ip_frame_head->version ) { inet_ntop(AF_INET6, &ip6_frame_head->ip6_src, src_ipv6_string, INET6_ADDRSTRLEN); inet_ntop(AF_INET6, &ip6_frame_head->ip6_dst, dst_ipv6_string, INET6_ADDRSTRLEN); GNB_LOG3(gnb_core->log,GNB_LOG_ID_PF,"inet dump[%"PRIu64"] [%llu]%s < [%llu]%s in:%u\n",seq, pf_ctx->dst_uuid64, dst_ipv6_string, pf_ctx->src_uuid64, src_ipv6_string, gnb_payload16_size(pf_ctx->fwd_payload)); } return pf_ctx->pf_status; } static void pf_release_cb(gnb_core_t *gnb_core, gnb_pf_t *pf){ } gnb_pf_t gnb_pf_dump = { .name = "gnb_pf_dump", .type = GNB_PF_TYEP_UNSET, .private_ctx = NULL, .pf_init = pf_init_cb, .pf_conf = pf_conf_cb, .pf_tun_frame = pf_tun_frame_cb, .pf_tun_route = pf_tun_route_cb, .pf_tun_fwd = pf_tun_fwd_cb, .pf_inet_frame = pf_inet_frame_cb, .pf_inet_route = pf_inet_route_cb, .pf_inet_fwd = pf_inet_fwd_cb, .pf_release = pf_release_cb }; opengnb-ver1.6.0.a/src/packet_filter/gnb_pf_route.c000077500000000000000000000505321500454252100223300ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 "gnb.h" #include "gnb_pf.h" #include "gnb_node.h" #include "gnb_payload16.h" #include "protocol/network_protocol.h" #define GNB_PAYLOAD_MAX_TTL 0x05 typedef struct _gnb_route_ctx_t { void *udata; }gnb_route_ctx_t; gnb_node_t* gnb_query_route4(gnb_core_t *gnb_core, uint32_t dst_ip_int); #pragma pack(push, 1) typedef struct _gnb_route_frame_head_t { unsigned char magic[2]; unsigned char pf_type_bits; //用于加密,压缩标识 uint8_t ttl; gnb_uuid_t src_uuid64; gnb_uuid_t dst_uuid64; unsigned char verifycode[4]; // 用于校验解密是否成功,暂未使用 } __attribute__ ((__packed__)) gnb_route_frame_head_t; #pragma pack(pop) #define MIN_ROUTE_FRAME_SIZE ( sizeof(gnb_route_frame_head_t) + sizeof(struct iphdr) ) static void pf_init_cb(gnb_core_t *gnb_core, gnb_pf_t *pf){ gnb_route_ctx_t *ctx = (gnb_route_ctx_t*)gnb_heap_alloc(gnb_core->heap,sizeof(gnb_route_ctx_t)); ctx->udata = NULL; pf->private_ctx = ctx; if ( 0 == gnb_core->tun_payload_offset ) { gnb_core->tun_payload_offset = sizeof(gnb_route_frame_head_t); } gnb_core->route_frame_head_size = sizeof(gnb_route_frame_head_t); GNB_LOG1(gnb_core->log, GNB_LOG_ID_PF, "%s init\n", pf->name); } static void pf_conf_cb(gnb_core_t *gnb_core, gnb_pf_t *pf){ } /* * 创建 route_frame ,填充 ip_frame, 得到dst_node */ static int pf_tun_frame_cb(gnb_core_t *gnb_core, gnb_pf_t *pf, gnb_pf_ctx_t *pf_ctx){ if ( NULL==pf_ctx->fwd_payload ) { return GNB_PF_ERROR; } //从payload中得到ip分组的首地址 struct iphdr *ip_frame_head; ip_frame_head = (struct iphdr*)(pf_ctx->fwd_payload->data + gnb_core->tun_payload_offset); //从ip分组中得到 dst ip,用于查路由表获得 dst node if ( 0x4 != ip_frame_head->version && 0x6 != ip_frame_head->version ) { return GNB_PF_DROP; } struct ip6_hdr *ip6_frame_head; uint32_t dst_ip_int; if ( 0x6 == ip_frame_head->version ) { ip6_frame_head = (struct ip6_hdr *)(pf_ctx->fwd_payload->data + gnb_core->tun_payload_offset); dst_ip_int = ip6_frame_head->ip6_dst.__in6_u.__u6_addr32[3]; pf_ctx->ipproto = ip6_frame_head->ip6_ctlun.ip6_un1.ip6_un1_nxt; goto handle_ip_frame; } if ( 0x4 == ip_frame_head->version ) { dst_ip_int = *((uint32_t *)&ip_frame_head->daddr); pf_ctx->ipproto =ip_frame_head->protocol; } handle_ip_frame: pf_ctx->dst_node = gnb_query_route4(gnb_core,dst_ip_int); if ( NULL==pf_ctx->dst_node ) { return GNB_PF_DROP; } if ( pf_ctx->dst_node == gnb_core->local_node ) { return GNB_PF_DROP; } //如果 dst node 与 本节点的 node 相同,而在tun设备中不会出现这个情况,因此可以判断这个ip frame是有问题的,drop掉 if ( pf_ctx->dst_node->tun_addr4.s_addr == gnb_core->local_node->tun_addr4.s_addr ) { return GNB_PF_DROP; } gnb_route_frame_head_t *route_frame_head; route_frame_head = (gnb_route_frame_head_t *)pf_ctx->fwd_payload->data; //在frame head 中填上magic number,接收方要检验 route_frame_head->magic[0] = 'S'; route_frame_head->magic[1] = 'U'; route_frame_head->pf_type_bits = gnb_core->conf->pf_bits; pf_ctx->pf_type_bits = &route_frame_head->pf_type_bits; route_frame_head->ttl = GNB_PAYLOAD_MAX_TTL; //把src和dst的 uuid64 保存在ctx中,route过程要用到 route_frame_head->src_uuid64 = gnb_htonll(gnb_core->local_node->uuid64); route_frame_head->dst_uuid64 = gnb_htonll(pf_ctx->dst_node->uuid64); pf_ctx->src_uuid64 = gnb_core->local_node->uuid64; pf_ctx->dst_uuid64 = pf_ctx->dst_node->uuid64; //把 ip frame 和 size,保存在ctx中,供后面的模块使用 pf_ctx->ip_frame = pf_ctx->fwd_payload->data + sizeof(gnb_route_frame_head_t); pf_ctx->ip_frame_size = gnb_payload16_data_len(pf_ctx->fwd_payload) - sizeof(gnb_route_frame_head_t); //这里肯定是 GNB_PF_FWD_INET ,来自本节点tun的分组不可能再发回本节点的tun/tap设备 pf_ctx->pf_fwd = GNB_PF_FWD_INET; return GNB_PF_NEXT; } /* * route,得到fwd_node */ static int pf_tun_route_cb(gnb_core_t *gnb_core, gnb_pf_t *pf, gnb_pf_ctx_t *pf_ctx){ int ret = GNB_PF_NEXT; uint8_t relay_count; uint16_t org_payload_size; uint16_t new_payload_size; gnb_uuid_t *relay_nodeid_ptr; int relay_nodeid_idx; gnb_node_t *last_relay_node; gnb_route_frame_head_t *route_frame_head = (gnb_route_frame_head_t *)pf_ctx->fwd_payload->data; if ( NULL == pf_ctx->dst_node ) { ret = GNB_PF_DROP; goto finish; } if ( 0 == gnb_core->conf->direct_forwarding ) { if ( NULL != gnb_core->select_fwd_node ) { pf_ctx->fwd_node = gnb_core->select_fwd_node; pf_ctx->std_forwarding = 1; ret = GNB_PF_NEXT; goto handle_relay; } else if ( gnb_core->fwdu0_address_ring.address_list->num > 0 ) { pf_ctx->universal_udp4_relay = 1; ret = GNB_PF_NOROUTE; goto finish; } else { ret = GNB_PF_ERROR; goto handle_relay; } } if ( (0 == gnb_core->fwd_node_ring.num ) && GNB_UNIFIED_FORWARDING_OFF==gnb_core->conf->unified_forwarding && ( (pf_ctx->dst_node->udp_addr_status & GNB_NODE_STATUS_IPV6_PING) || (pf_ctx->dst_node->udp_addr_status & GNB_NODE_STATUS_IPV4_PING) ) ) { pf_ctx->fwd_node = pf_ctx->dst_node; pf_ctx->direct_forwarding = 1; ret = GNB_PF_NEXT; goto handle_relay; } //设置了 direct_forward 且 dst_node 状态是激活状态,fwd_node 就是 dst_node if ( (pf_ctx->dst_node->udp_addr_status & GNB_NODE_STATUS_IPV6_PONG) || (pf_ctx->dst_node->udp_addr_status & GNB_NODE_STATUS_IPV4_PONG) ) { pf_ctx->fwd_node = pf_ctx->dst_node; pf_ctx->direct_forwarding = 1; ret = GNB_PF_NEXT; goto handle_relay; } if ( gnb_core->fwdu0_address_ring.address_list->num > 0 && NULL == gnb_core->select_fwd_node ) { ret = GNB_PF_NOROUTE; goto handle_relay; } if ( NULL == gnb_core->select_fwd_node ) { ret = GNB_PF_DROP; goto handle_relay; } if ( (gnb_core->select_fwd_node->udp_addr_status & GNB_NODE_STATUS_IPV6_PONG) || (gnb_core->select_fwd_node->udp_addr_status & GNB_NODE_STATUS_IPV4_PONG) ) { pf_ctx->fwd_node = gnb_core->select_fwd_node; pf_ctx->fwd_payload->sub_type |= GNB_PAYLOAD_SUB_TYPE_IPFRAME_STD; pf_ctx->std_forwarding = 1; ret = GNB_PF_NEXT; goto handle_relay; } else { ret = GNB_PF_DROP; goto handle_relay; } handle_relay: if ( GNB_NODE_RELAY_DISABLE == pf_ctx->dst_node->node_relay_mode ) { goto finish_relay; } if ( GNB_PF_NEXT == ret && (GNB_NODE_RELAY_AUTO & pf_ctx->dst_node->node_relay_mode) ) { goto finish_relay; } if ( !( (GNB_NODE_RELAY_FORCE|GNB_NODE_RELAY_AUTO) & pf_ctx->dst_node->node_relay_mode ) ) { goto finish_relay; } relay_count = pf_ctx->dst_node->route_node_ttls[pf_ctx->dst_node->selected_route_node]; if ( 0 == relay_count || relay_count > GNB_MAX_NODE_RELAY ) { goto finish_relay; } pf_ctx->fwd_payload->sub_type |= GNB_PAYLOAD_SUB_TYPE_IPFRAME_RELAY; if ( GNB_NODE_RELAY_STATIC & pf_ctx->dst_node->node_relay_mode ) { pf_ctx->dst_node->selected_route_node = 0; } relay_nodeid_ptr = pf_ctx->relay_nodeid_array; for ( relay_nodeid_idx=0; relay_nodeid_idx < relay_count; relay_nodeid_idx++ ) { relay_nodeid_ptr[ relay_nodeid_idx ] = gnb_htonll( pf_ctx->dst_node->route_node[ pf_ctx->dst_node->selected_route_node ][ relay_nodeid_idx ] ); } relay_nodeid_ptr[ relay_nodeid_idx ] = gnb_htonll(gnb_core->local_node->uuid64); memcpy((pf_ctx->fwd_payload->data + sizeof(gnb_route_frame_head_t) + pf_ctx->ip_frame_size ), relay_nodeid_ptr, sizeof(gnb_uuid_t)*(relay_count+1)); org_payload_size = gnb_payload16_size(pf_ctx->fwd_payload); route_frame_head->ttl = relay_count + 1; new_payload_size = org_payload_size + relay_count*sizeof(gnb_uuid_t) + sizeof(gnb_uuid_t); if ( new_payload_size > gnb_core->conf->payload_block_size ) { ret = GNB_PF_DROP; goto finish_relay; } gnb_payload16_set_size(pf_ctx->fwd_payload, new_payload_size); pf_ctx->fwd_node = GNB_HASH32_UINT64_GET_PTR(gnb_core->uuid_node_map, pf_ctx->dst_node->route_node[ pf_ctx->dst_node->selected_route_node ][ relay_count-1 ]); if ( NULL==pf_ctx->fwd_node ) { ret = GNB_PF_NOROUTE; goto finish_relay; } pf_ctx->relay_forwarding = 1; route_frame_head->pf_type_bits = gnb_core->conf->pf_bits; ret = GNB_PF_NEXT; if ( GNB_NODE_RELAY_BALANCE & pf_ctx->dst_node->node_relay_mode ) { pf_ctx->dst_node->selected_route_node++; if ( 0 == pf_ctx->dst_node->route_node[pf_ctx->dst_node->selected_route_node][0] ) { pf_ctx->dst_node->selected_route_node = 0; } } if ( 1==gnb_core->conf->if_dump ) { for ( relay_nodeid_idx=0; relay_nodeid_idxlog, GNB_LOG_ID_PF, "pf_tun_route_cb idx=%u relay node=%llu\n", relay_nodeid_idx, pf_ctx->dst_node->route_node[ pf_ctx->dst_node->selected_route_node ][ relay_nodeid_idx ]); } } finish_relay: if ( 0==pf_ctx->relay_forwarding ) { if ( 0 == pf_ctx->dst_node->last_relay_nodeid ) { goto finish; } if ( 0 == pf_ctx->dst_node->last_relay_node_ts_sec || (gnb_core->now_time_sec - pf_ctx->dst_node->last_relay_node_ts_sec) > GNB_LAST_RELAY_NODE_EXPIRED_SEC ) { goto finish; } last_relay_node = GNB_HASH32_UINT64_GET_PTR(gnb_core->uuid_node_map, pf_ctx->dst_node->last_relay_nodeid); if ( NULL==last_relay_node ) { goto finish; } if ( (last_relay_node->udp_addr_status & GNB_NODE_STATUS_IPV6_PONG) || (last_relay_node->udp_addr_status & GNB_NODE_STATUS_IPV4_PONG) ) { pf_ctx->fwd_node = last_relay_node; ret = GNB_PF_NEXT; GNB_LOG3(gnb_core->log, GNB_LOG_ID_PF, "pf_tun_route_cb forward through last relay node %llu => %llu => %llu\n", gnb_core->local_node->uuid64, last_relay_node->uuid64, pf_ctx->dst_node->uuid64 ); } } finish: GNB_LOG4(gnb_core->log, GNB_LOG_ID_PF, "pf_tun_route_cb [%llu]>[%llu] pf_ctx->in_ttl[%u] route_frame_head->ttl[%u] ip_frame_size[%d]\n", pf_ctx->src_uuid64, pf_ctx->dst_uuid64, pf_ctx->in_ttl, route_frame_head->ttl, pf_ctx->ip_frame_size); return ret; } static int pf_inet_frame_cb(gnb_core_t *gnb_core, gnb_pf_t *pf, gnb_pf_ctx_t *pf_ctx){ int ret = GNB_PF_NEXT; uint16_t payload_data_size; gnb_uuid_t *relay_nodeid_ptr; gnb_route_frame_head_t *route_frame_head; int i; if ( NULL == pf_ctx->fwd_payload ) { ret = GNB_PF_ERROR; goto finish; } payload_data_size = gnb_payload16_data_len(pf_ctx->fwd_payload); if( payload_data_size < MIN_ROUTE_FRAME_SIZE ) { ret = GNB_PF_ERROR; goto finish; } //从payload中得到 route_frame 首地址 route_frame_head = (gnb_route_frame_head_t *)pf_ctx->fwd_payload->data; //检查magic number是否正确,如果不正确,那有可能是对端发来的payload不对,或者前面接收模块对数据处理不对 if ( route_frame_head->magic[0] != 'S' || route_frame_head->magic[1] != 'U' ) { ret = GNB_PF_ERROR; goto finish; } pf_ctx->src_uuid64 = gnb_ntohll(route_frame_head->src_uuid64); pf_ctx->dst_uuid64 = gnb_ntohll(route_frame_head->dst_uuid64); pf_ctx->pf_type_bits = &route_frame_head->pf_type_bits; if ( route_frame_head->ttl > GNB_PAYLOAD_MAX_TTL ) { ret = GNB_PF_DROP; goto finish; } pf_ctx->in_ttl = route_frame_head->ttl; if ( route_frame_head->ttl > 0) { route_frame_head->ttl--; } if (gnb_core->local_node->uuid64 == pf_ctx->dst_uuid64) { route_frame_head->ttl = 0; } //把 ip frame 和 size,保存在ctx中 pf_ctx->ip_frame = pf_ctx->fwd_payload->data + sizeof(gnb_route_frame_head_t); if ( !(GNB_PAYLOAD_SUB_TYPE_IPFRAME_RELAY & pf_ctx->fwd_payload->sub_type) ) { pf_ctx->ip_frame_size = gnb_payload16_data_len(pf_ctx->fwd_payload) - sizeof(gnb_route_frame_head_t); } else { // 处理带有 GNB_PAYLOAD_SUB_TYPE_IPFRAME_RELAY 标志的 payload pf_ctx->ip_frame_size = gnb_payload16_data_len(pf_ctx->fwd_payload) - sizeof(gnb_route_frame_head_t) - pf_ctx->in_ttl*sizeof(gnb_uuid_t); relay_nodeid_ptr = pf_ctx->relay_nodeid_array; memcpy((void *)relay_nodeid_ptr, pf_ctx->fwd_payload->data + sizeof(gnb_route_frame_head_t) + pf_ctx->ip_frame_size, sizeof(gnb_uuid_t) * GNB_MAX_NODE_RELAY); pf_ctx->src_fwd_uuid64 = gnb_ntohll(pf_ctx->relay_nodeid_array[ pf_ctx->in_ttl -1 ]); } ret = GNB_PF_NEXT; finish: if ( 1==gnb_core->conf->if_dump ) { if( GNB_PAYLOAD_SUB_TYPE_IPFRAME_RELAY & pf_ctx->fwd_payload->sub_type ) { GNB_LOG3(gnb_core->log, GNB_LOG_ID_PF, "pf_inet_frame_cb src_fwd[%llu] [%llu]>[%llu] in_ttl[%u] ip_frame_size[%u]\n", pf_ctx->src_fwd_uuid64, pf_ctx->src_uuid64, pf_ctx->dst_uuid64, pf_ctx->in_ttl, pf_ctx->ip_frame_size); for ( i=0; iin_ttl; i++ ) { GNB_LOG3(gnb_core->log, GNB_LOG_ID_PF, "pf_inet_frame_cb [%llu]>[%llu] relay[%llu]\n", pf_ctx->src_uuid64, pf_ctx->dst_uuid64, gnb_ntohll(pf_ctx->relay_nodeid_array[i]) ); } } else { GNB_LOG3(gnb_core->log, GNB_LOG_ID_PF, "pf_inet_frame_cb [%llu]>[%llu] in_ttl[%u] ip_frame_size[%u]\n", pf_ctx->src_uuid64, pf_ctx->dst_uuid64, pf_ctx->in_ttl, pf_ctx->ip_frame_size); } } return ret; } static int pf_inet_route_cb(gnb_core_t *gnb_core, gnb_pf_t *pf, gnb_pf_ctx_t *pf_ctx){ gnb_route_frame_head_t *route_frame_head; gnb_payload16_t *payload_in = pf_ctx->fwd_payload; route_frame_head = (gnb_route_frame_head_t *)payload_in->data; int ret = GNB_PF_NEXT; gnb_uuid_t *src_fwd_nodeid_ptr; gnb_uuid_t *relay_nodeid_ptr; gnb_uuid_t relay_nodeid; gnb_uuid_t current_nodeid; uint16_t payload_data_size; int i; gnb_uuid_t *nodeid_ptr; payload_data_size = GNB_PAYLOAD16_DATA_SIZE(pf_ctx->fwd_payload); pf_ctx->src_node = GNB_HASH32_UINT64_GET_PTR(gnb_core->uuid_node_map, pf_ctx->src_uuid64); if ( NULL==pf_ctx->src_node ) { ret = GNB_PF_DROP; goto finish; } if ( gnb_core->local_node->uuid64 == pf_ctx->dst_uuid64 ) { // 如果设置了加密和压缩 此时 ip_frame 还没解密和解压 pf_ctx->pf_fwd = GNB_PF_FWD_TUN; ret = GNB_PF_NEXT; if ( GNB_PAYLOAD_SUB_TYPE_IPFRAME_RELAY & pf_ctx->fwd_payload->sub_type ) { pf_ctx->src_node->last_relay_nodeid = gnb_ntohll(pf_ctx->relay_nodeid_array[pf_ctx->in_ttl-1]); pf_ctx->src_node->last_relay_node_ts_sec = gnb_core->now_time_sec; GNB_LOG3(gnb_core->log, GNB_LOG_ID_PF, "pf_inet_route_cb GNB_PAYLOAD_SUB_TYPE_IPFRAME_RELAY src_nodeid=%llu set last_relay_nodeid=%llu\n", pf_ctx->src_node->uuid64, pf_ctx->src_node->last_relay_nodeid); } else { pf_ctx->src_node->last_relay_nodeid = 0; pf_ctx->src_node->last_relay_node_ts_sec = 0l; } goto finish; } if ( 0x0 == route_frame_head->ttl ) { ret = GNB_PF_DROP; goto finish; } if ( GNB_PAYLOAD_SUB_TYPE_IPFRAME_RELAY & pf_ctx->fwd_payload->sub_type ) { goto route_relay; } route_default: //如果目标节点不是本地就尝试往默认路由发 if ( !gnb_core->conf->standard_forwarding ) { ret = GNB_PF_DROP; goto finish; } pf_ctx->dst_node = GNB_HASH32_UINT64_GET_PTR(gnb_core->uuid_node_map, pf_ctx->dst_uuid64); if ( NULL != pf_ctx->dst_node ) { pf_ctx->fwd_node = pf_ctx->dst_node; pf_ctx->pf_fwd = GNB_PF_FWD_INET; } else { pf_ctx->fwd_node = gnb_core->select_fwd_node; pf_ctx->pf_fwd = GNB_PF_FWD_INET; } ret = GNB_PF_NEXT; if ( 1==gnb_core->conf->if_dump ) { GNB_LOG3(gnb_core->log, GNB_LOG_ID_PF, "pf_inet_route_cb [%llu]>[%llu] out_ttl[%u] ip_frame_size[%u] route node\n", pf_ctx->src_uuid64, pf_ctx->dst_uuid64, route_frame_head->ttl, pf_ctx->ip_frame_size); } goto finish; route_relay: if ( pf_ctx->in_ttl <= 1 ) { //不可能到这里 ret = GNB_PF_ERROR; goto finish; } src_fwd_nodeid_ptr = &pf_ctx->relay_nodeid_array[pf_ctx->in_ttl - 1]; current_nodeid = gnb_ntohll( *(src_fwd_nodeid_ptr-1) ); if ( pf_ctx->in_ttl > 2 ) { // 下一个要转发的 node id relay_nodeid_ptr = src_fwd_nodeid_ptr-2; if ( current_nodeid != gnb_core->local_node->uuid64 ) { ret = GNB_PF_ERROR; goto finish; } } else { relay_nodeid_ptr = NULL; } if ( NULL != relay_nodeid_ptr ) { relay_nodeid = gnb_ntohll( *relay_nodeid_ptr ); if ( relay_nodeid==gnb_core->local_node->uuid64 ) { ret = GNB_PF_ERROR; goto finish; } } else { relay_nodeid = pf_ctx->dst_uuid64; } pf_ctx->dst_node = GNB_HASH32_UINT64_GET_PTR(gnb_core->uuid_node_map, relay_nodeid); if ( NULL == pf_ctx->dst_node ) { ret = GNB_PF_NOROUTE; goto finish; } pf_ctx->fwd_node = pf_ctx->dst_node; pf_ctx->pf_fwd = GNB_PF_FWD_INET; gnb_payload16_set_data_len(pf_ctx->fwd_payload, payload_data_size - sizeof(gnb_uuid_t) ); ret = GNB_PF_NEXT; if ( 1==gnb_core->conf->if_dump ) { GNB_LOG3(gnb_core->log, GNB_LOG_ID_PF, "pf_inet_route_cb [%llu]>[%llu] out_ttl[%u] ip_frame_size[%u] route relay node\n", pf_ctx->src_uuid64, pf_ctx->dst_uuid64, route_frame_head->ttl, pf_ctx->ip_frame_size); for ( i=0; i<(pf_ctx->in_ttl-1); i++ ) { GNB_LOG3( gnb_core->log,GNB_LOG_ID_PF, "pf_inet_route_cb [%llu]>[%llu] in_ttl[%u] relay[%llu]\n", pf_ctx->src_uuid64, pf_ctx->dst_uuid64, pf_ctx->in_ttl, gnb_ntohll(pf_ctx->relay_nodeid_array[i])); } } finish: return ret; } static int pf_inet_fwd_cb(gnb_core_t *gnb_core, gnb_pf_t *pf, gnb_pf_ctx_t *pf_ctx){ if ( GNB_PF_FWD_TUN != pf_ctx->pf_fwd ) { return pf_ctx->pf_status; } struct iphdr *ip_frame_head = (struct iphdr *)pf_ctx->ip_frame; struct ip6_hdr *ip6_frame_head = (struct ip6_hdr*)pf_ctx->ip_frame; uint32_t dst_ip_int; gnb_node_t *dst_node; if ( 0x6 == ip_frame_head->version ) { ip6_frame_head = (struct ip6_hdr *)(pf_ctx->fwd_payload->data + gnb_core->tun_payload_offset); dst_ip_int = ip6_frame_head->ip6_dst.__in6_u.__u6_addr32[3]; pf_ctx->ipproto = ip6_frame_head->ip6_ctlun.ip6_un1.ip6_un1_nxt; } else if ( 0x4 == ip_frame_head->version ) { dst_ip_int = *((uint32_t *)&ip_frame_head->daddr); pf_ctx->ipproto =ip_frame_head->protocol; } else { pf_ctx->pf_status = GNB_PF_ERROR; goto finish; } //根据目的ip地址做检查 dst_node = gnb_query_route4(gnb_core,dst_ip_int); if ( NULL == dst_node ) { pf_ctx->pf_status = GNB_PF_NOROUTE; } finish: return pf_ctx->pf_status; } static void pf_release_cb(gnb_core_t *gnb_core, gnb_pf_t *pf){ } gnb_pf_t gnb_pf_route = { .name = "gnb_pf_route", .type = GNB_PF_TYEP_UNSET, .private_ctx = NULL, .pf_init = pf_init_cb, .pf_conf = pf_conf_cb, .pf_tun_frame = pf_tun_frame_cb, .pf_tun_route = pf_tun_route_cb, .pf_tun_fwd = NULL, .pf_inet_frame = pf_inet_frame_cb, .pf_inet_route = pf_inet_route_cb, .pf_inet_fwd = pf_inet_fwd_cb, .pf_release = pf_release_cb }; opengnb-ver1.6.0.a/src/packet_filter/gnb_pf_zip.c000077500000000000000000000211221500454252100217650ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 "gnb.h" #include "gnb_payload16.h" #include "protocol/network_protocol.h" #include "zlib/zlib.h" #include "gnb_binary.h" typedef struct _gnb_pf_private_ctx_t { uint32_t max_deflate_chunk_size; uint32_t max_inflate_chunk_size; z_stream deflate_strm; gnb_payload16_t *deflated_payload; z_stream inflate_strm; gnb_payload16_t *inflate_payload; }gnb_pf_private_ctx_t; gnb_pf_t gnb_pf_zip; static void pf_init_cb(gnb_core_t *gnb_core, gnb_pf_t *pf){ int ret; gnb_pf_private_ctx_t *ctx = (gnb_pf_private_ctx_t*)gnb_heap_alloc(gnb_core->heap,sizeof(gnb_pf_private_ctx_t)); ctx->max_deflate_chunk_size = gnb_core->conf->payload_block_size; ctx->max_inflate_chunk_size = gnb_core->conf->payload_block_size; if ( 0==gnb_core->conf->pf_worker_num ) { ctx->deflated_payload = (gnb_payload16_t *)gnb_core->ctl_block->core_zone->pf_worker_payload_blocks; } else { ctx->deflated_payload = (gnb_payload16_t *)(gnb_core->ctl_block->core_zone->pf_worker_payload_blocks + (sizeof(gnb_payload16_t) + gnb_core->conf->payload_block_size + sizeof(gnb_payload16_t) + gnb_core->conf->payload_block_size ) * (1+gnb_core->pf_worker_ring->cur_idx)); } ctx->inflate_payload = (gnb_payload16_t *)((unsigned char *)ctx->deflated_payload + sizeof(gnb_payload16_t) + gnb_core->conf->payload_block_size); ctx->deflate_strm.zalloc = Z_NULL; ctx->deflate_strm.zfree = Z_NULL; ctx->deflate_strm.opaque = Z_NULL; if ( 0==gnb_core->conf->zip_level ) { ret = deflateInit(&ctx->deflate_strm, Z_DEFAULT_COMPRESSION); } else { ret = deflateInit(&ctx->deflate_strm, gnb_core->conf->zip_level); } if ( ret != Z_OK ) { GNB_LOG1(gnb_core->log,GNB_LOG_ID_PF, "%s deflateInit error\n", gnb_pf_zip.name); } ctx->inflate_strm.zalloc = Z_NULL; ctx->inflate_strm.zfree = Z_NULL; ctx->inflate_strm.opaque = Z_NULL; ret = inflateInit(&ctx->inflate_strm); if ( ret != Z_OK ) { GNB_LOG1(gnb_core->log, GNB_LOG_ID_PF, "%s inflateInit error\n", gnb_pf_zip.name); } pf->private_ctx = ctx; GNB_LOG1(gnb_core->log, GNB_LOG_ID_PF, "%s init\n", pf->name); } static void pf_conf_cb(gnb_core_t *gnb_core, gnb_pf_t *pf){ } /* deflate 压缩 payload 对 pf_ctx->ip_frame 起 pf_ctx->ip_frame_size 个字节压缩 对于包含 GNB_PAYLOAD_SUB_TYPE_IPFRAME_RELAY 标志的 payload 尾部的relay node id 数组需要保留 */ static int pf_tun_route_cb(gnb_core_t *gnb_core, gnb_pf_t *pf, gnb_pf_ctx_t *pf_ctx){ int ret; int deflate_chunk_size; //uint16_t in_payload_data_len; uint16_t frame_header_size; uint16_t frame_tail_size; if ( 0==gnb_core->conf->zip_level ) { return pf_ctx->pf_status; } frame_header_size = gnb_core->tun_payload_offset; gnb_pf_private_ctx_t *ctx = pf->private_ctx; deflateReset(&ctx->deflate_strm); ctx->deflate_strm.next_in = pf_ctx->ip_frame; ctx->deflate_strm.avail_in = pf_ctx->ip_frame_size; ctx->deflate_strm.next_out = ctx->deflated_payload->data + frame_header_size; ctx->deflate_strm.avail_out = gnb_core->conf->payload_block_size; ret = deflate(&ctx->deflate_strm, Z_FINISH); if ( ret != Z_STREAM_END ) { return GNB_PF_ERROR; } // deflate_chunk_size is new ip_frame_size deflate_chunk_size = gnb_core->conf->payload_block_size - ctx->deflate_strm.avail_out; if ( deflate_chunk_size >= gnb_core->conf->payload_block_size ) { return GNB_PF_ERROR; } if( deflate_chunk_size >= gnb_core->conf->payload_block_size ) { return GNB_PF_ERROR; } if ( GNB_ZIP_AUTO == gnb_core->conf->zip && deflate_chunk_size >= pf_ctx->ip_frame_size ) { GNB_LOG3(gnb_core->log, GNB_LOG_ID_PF, "Deflate Skip in payload ip_frame_size=%d deflate chunk size=%d\n", pf_ctx->ip_frame_size, deflate_chunk_size); goto skip_deflate; } GNB_LOG3(gnb_core->log, GNB_LOG_ID_PF, "Deflate in payload size=%d deflate_chunk_size=%d\n", pf_ctx->ip_frame_size, deflate_chunk_size); ctx->deflated_payload->type = pf_ctx->fwd_payload->type; ctx->deflated_payload->sub_type = pf_ctx->fwd_payload->sub_type | GNB_PAYLOAD_SUB_TYPE_IPFRAME_ZIP; //拷贝 ip_frame 前的 frame header 数据 memcpy(ctx->deflated_payload->data, pf_ctx->fwd_payload->data, gnb_core->tun_payload_offset); if ( !(pf_ctx->fwd_payload->sub_type & GNB_PAYLOAD_SUB_TYPE_IPFRAME_RELAY) ) { gnb_payload16_set_data_len(ctx->deflated_payload, frame_header_size + deflate_chunk_size); } else { //GNB_PAYLOAD_SUB_TYPE_IPFRAME_RELAY //拷贝 ip_frame 后的数据 frame_tail_size = gnb_payload16_data_len(pf_ctx->fwd_payload) - frame_header_size - pf_ctx->ip_frame_size; memcpy((ctx->deflated_payload->data + frame_header_size + deflate_chunk_size), (pf_ctx->ip_frame + pf_ctx->ip_frame_size), frame_tail_size); gnb_payload16_set_data_len(ctx->deflated_payload, frame_header_size + deflate_chunk_size + frame_tail_size); } pf_ctx->fwd_payload = ctx->deflated_payload; //重新指定 ip_frame 位置 和 ip_frame_size pf_ctx->ip_frame = pf_ctx->fwd_payload->data + frame_header_size; pf_ctx->ip_frame_size = deflate_chunk_size; skip_deflate: return GNB_PF_NEXT; } /* inflate 解压 payload */ static int pf_inet_route(gnb_core_t *gnb_core, gnb_pf_t *pf, gnb_pf_ctx_t *pf_ctx){ int ret; int inflate_chunk_size; uint16_t in_payload_data_len; uint16_t frame_header_size; if ( 0==gnb_core->conf->zip_level ) { return pf_ctx->pf_status; } if ( !(pf_ctx->fwd_payload->sub_type & GNB_PAYLOAD_SUB_TYPE_IPFRAME_ZIP) ) { return pf_ctx->pf_status; } //目标节点不是本地节点,就不要解压数据 if ( pf_ctx->dst_uuid64 != gnb_core->local_node->uuid64 ) { return pf_ctx->pf_status; } frame_header_size = gnb_core->tun_payload_offset; gnb_pf_private_ctx_t *ctx = pf->private_ctx; inflateReset(&ctx->inflate_strm); in_payload_data_len = gnb_payload16_data_len(pf_ctx->fwd_payload); ctx->inflate_strm.next_in = pf_ctx->fwd_payload->data + frame_header_size; ctx->inflate_strm.avail_in = in_payload_data_len - frame_header_size; ctx->inflate_strm.next_out = ctx->inflate_payload->data + frame_header_size; ctx->inflate_strm.avail_out = gnb_core->conf->payload_block_size; ret = inflate(&ctx->inflate_strm, Z_FINISH); if ( ret != Z_STREAM_END ) { return GNB_PF_ERROR; } inflate_chunk_size = gnb_core->conf->payload_block_size - ctx->inflate_strm.avail_out; GNB_LOG3(gnb_core->log, GNB_LOG_ID_PF, "Inflate payload size=%d inflate_chunk_size=%d\n", in_payload_data_len, inflate_chunk_size); ctx->inflate_payload->type = pf_ctx->fwd_payload->type; ctx->inflate_payload->sub_type = pf_ctx->fwd_payload->sub_type; memcpy(ctx->inflate_payload->data, pf_ctx->fwd_payload->data, frame_header_size); pf_ctx->fwd_payload = ctx->inflate_payload; //new ip_frame_size pf_ctx->ip_frame_size = inflate_chunk_size; //new payload size gnb_payload16_set_data_len(pf_ctx->fwd_payload, frame_header_size + pf_ctx->ip_frame_size); pf_ctx->ip_frame = pf_ctx->fwd_payload->data + frame_header_size; return GNB_PF_NEXT; } static void pf_release_cb(gnb_core_t *gnb_core, gnb_pf_t *pf){ } gnb_pf_t gnb_pf_zip = { .name = "gnb_pf_zip", .type = GNB_PF_TYEP_UNSET, .private_ctx = NULL, .pf_init = pf_init_cb, .pf_conf = pf_conf_cb, .pf_tun_frame = NULL, // pf_tun_frame .pf_tun_route = pf_tun_route_cb, // pf_tun_route .pf_tun_fwd = NULL, // pf_tun_fwd .pf_inet_frame = NULL, // pf_inet_frame .pf_inet_route = pf_inet_route, // pf_inet_route .pf_inet_fwd = NULL, // pf_inet_fwd .pf_release = pf_release_cb // pf_release }; opengnb-ver1.6.0.a/src/unix/000077500000000000000000000000001500454252100156525ustar00rootroot00000000000000opengnb-ver1.6.0.a/src/unix/unix_platform.c000077500000000000000000000052451500454252100207160ustar00rootroot00000000000000/* Copyright (C) gnbdev 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 #include #include #include #include #include "gnb_exec.h" #include "gnb_arg_list.h" #if defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) extern char **__environ; #endif #if defined(GNB_OPENWRT_BUILD) extern char **environ; #endif #if defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__) extern char **environ; #endif int gnb_get_pid(){ int pid = getpid(); return pid; } void gnb_set_env(const char *name, const char *value){ setenv(name, value, 1); } pid_t gnb_exec(char *app_filename, char *current_path, gnb_arg_list_t *arg_list, int flag){ pid_t pid; int fd; int ret; int argc = 0; char *argv[arg_list->argc]; pid = fork(); if ( 0 != pid ) { if ( -1 == pid ) { return pid; } if ( flag & GNB_EXEC_WAIT ) { waitpid(pid, NULL, 0); } return pid; } int i; for (i=0; iargc; i++) { argv[i] = arg_list->argv[i]; } argv[i] = NULL; ret = chdir(current_path); if ( 0 != ret ) { goto finish; } if ( flag & GNB_EXEC_FOREGROUND ) { goto do_exec; } fd = open("/dev/null", O_RDWR); if ( 0 != fd ){ ret = dup2(fd, STDIN_FILENO); ret = dup2(fd, STDOUT_FILENO); ret = dup2(fd, STDERR_FILENO); } do_exec: #if defined(__linux__) #if defined(GNB_LINUX_BUILD) ret = execve(app_filename, argv, __environ); #endif #if defined(GNB_OPENWRT_BUILD) ret = execve(app_filename, argv, environ); #endif #if defined(GNB_ANDROID_BUILD) ret = execve(app_filename, argv, environ); #endif #endif #if defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__) ret = execve(app_filename, argv, environ); #endif if ( -1==ret ) { goto finish; } finish: exit(0); return 0; } void gnb_kill(pid_t pid){ kill(pid, SIGKILL); } opengnb-ver1.6.0.a/version000066400000000000000000000000101500454252100154770ustar00rootroot000000000000001.6.0.a