pax_global_header 0000666 0000000 0000000 00000000064 15004542521 0014510 g ustar 00root root 0000000 0000000 52 comment=773e1fb7b5a0cfc89d1b88f0aeebfc3fcc71e8c3
opengnb-ver1.6.0.a/ 0000775 0000000 0000000 00000000000 15004542521 0014100 5 ustar 00root root 0000000 0000000 opengnb-ver1.6.0.a/.gitattributes 0000664 0000000 0000000 00000000031 15004542521 0016765 0 ustar 00root root 0000000 0000000 *.sh linguist-language=c
opengnb-ver1.6.0.a/.gitignore 0000664 0000000 0000000 00000000701 15004542521 0016066 0 ustar 00root root 0000000 0000000 # 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/LICENSE 0000664 0000000 0000000 00000104515 15004542521 0015113 0 ustar 00root root 0000000 0000000 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.Darwin 0000664 0000000 0000000 00000003117 15004542521 0016765 0 ustar 00root root 0000000 0000000 CFLAGS=-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.freebsd 0000664 0000000 0000000 00000003066 15004542521 0017156 0 ustar 00root root 0000000 0000000 CFLAGS=-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.inc 0000664 0000000 0000000 00000013636 15004542521 0016321 0 ustar 00root root 0000000 0000000 MINIUPNP_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.linux 0000664 0000000 0000000 00000003253 15004542521 0016701 0 ustar 00root root 0000000 0000000 CFLAGS=-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_64 0000664 0000000 0000000 00000003733 15004542521 0017704 0 ustar 00root root 0000000 0000000 CFLAGS=-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.openbsd 0000664 0000000 0000000 00000002737 15004542521 0017202 0 ustar 00root root 0000000 0000000 CFLAGS=-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.openwrt 0000664 0000000 0000000 00000003232 15004542521 0017235 0 ustar 00root root 0000000 0000000 CFLAGS=-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.md 0000664 0000000 0000000 00000024612 15004542521 0015364 0 ustar 00root root 0000000 0000000 # 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.md 0000664 0000000 0000000 00000023435 15004542521 0015746 0 ustar 00root root 0000000 0000000 # 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/ 0000775 0000000 0000000 00000000000 15004542521 0015030 5 ustar 00root root 0000000 0000000 opengnb-ver1.6.0.a/docs/disclaimer_cn.md 0000664 0000000 0000000 00000001743 15004542521 0020153 0 ustar 00root root 0000000 0000000 # 免责声明
[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.md 0000664 0000000 0000000 00000005413 15004542521 0020454 0 ustar 00root root 0000000 0000000 [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.md 0000664 0000000 0000000 00000121515 15004542521 0021200 0 ustar 00root root 0000000 0000000 OpenGNB 用户手册
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.md 0000664 0000000 0000000 00000133533 15004542521 0021205 0 ustar 00root root 0000000 0000000 OpenGNB 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/ 0000775 0000000 0000000 00000000000 15004542521 0015716 5 ustar 00root root 0000000 0000000 opengnb-ver1.6.0.a/examples/node_config_example/ 0000775 0000000 0000000 00000000000 15004542521 0021703 5 ustar 00root root 0000000 0000000 opengnb-ver1.6.0.a/examples/node_config_example/address.conf 0000664 0000000 0000000 00000000030 15004542521 0024170 0 ustar 00root root 0000000 0000000 i|0|101.32.178.3|9001
opengnb-ver1.6.0.a/examples/node_config_example/node.conf 0000664 0000000 0000000 00000000443 15004542521 0023500 0 ustar 00root root 0000000 0000000 #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.conf 0000664 0000000 0000000 00000000215 15004542521 0023706 0 ustar 00root root 0000000 0000000 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
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/ 0000775 0000000 0000000 00000000000 15004542521 0023372 5 ustar 00root root 0000000 0000000 opengnb-ver1.6.0.a/examples/node_config_example/scripts/if_down_darwin.sh 0000775 0000000 0000000 00000000317 15004542521 0026723 0 ustar 00root root 0000000 0000000 #!/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.sh 0000775 0000000 0000000 00000000112 15004542521 0027042 0 ustar 00root root 0000000 0000000 #!/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.sh 0000775 0000000 0000000 00000000131 15004542521 0026570 0 ustar 00root root 0000000 0000000 #!/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.sh 0000775 0000000 0000000 00000000107 15004542521 0027066 0 ustar 00root root 0000000 0000000 #!/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.sh 0000775 0000000 0000000 00000000111 15004542521 0026370 0 ustar 00root root 0000000 0000000 #!/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.sh 0000775 0000000 0000000 00000000112 15004542521 0026517 0 ustar 00root root 0000000 0000000 #!/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.sh 0000775 0000000 0000000 00000000127 15004542521 0026252 0 ustar 00root root 0000000 0000000 #!/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.sh 0000775 0000000 0000000 00000000111 15004542521 0026536 0 ustar 00root root 0000000 0000000 #!/bin/sh
#GNB ENV $GNB_IF_NAME $GNB_MTU $GNB_TUN_IPV4 $GNB_TUN_IPV6
opengnb-ver1.6.0.a/libs/ 0000775 0000000 0000000 00000000000 15004542521 0015031 5 ustar 00root root 0000000 0000000 opengnb-ver1.6.0.a/libs/README.md 0000664 0000000 0000000 00000001453 15004542521 0016313 0 ustar 00root root 0000000 0000000 # 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/ 0000775 0000000 0000000 00000000000 15004542521 0016027 5 ustar 00root root 0000000 0000000 opengnb-ver1.6.0.a/libs/ed25519/add_scalar.c 0000664 0000000 0000000 00000004172 15004542521 0020254 0 ustar 00root root 0000000 0000000 #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.h 0000664 0000000 0000000 00000002343 15004542521 0017200 0 ustar 00root root 0000000 0000000 #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.c 0000664 0000000 0000000 00000113673 15004542521 0016600 0 ustar 00root root 0000000 0000000 #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.h 0000664 0000000 0000000 00000001724 15004542521 0016576 0 ustar 00root root 0000000 0000000 #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.h 0000664 0000000 0000000 00000004726 15004542521 0020023 0 ustar 00root root 0000000 0000000 /*
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.c 0000664 0000000 0000000 00000024205 15004542521 0016571 0 ustar 00root root 0000000 0000000 #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.h 0000664 0000000 0000000 00000003223 15004542521 0016573 0 ustar 00root root 0000000 0000000 #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.c 0000664 0000000 0000000 00000003431 15004542521 0020626 0 ustar 00root root 0000000 0000000 #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.c 0000664 0000000 0000000 00000000574 15004542521 0017645 0 ustar 00root root 0000000 0000000 #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.txt 0000664 0000000 0000000 00000001552 15004542521 0020215 0 ustar 00root root 0000000 0000000 Copyright (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.h 0000664 0000000 0000000 00000277010 15004542521 0020645 0 ustar 00root root 0000000 0000000 static 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.c 0000664 0000000 0000000 00000054523 15004542521 0016611 0 ustar 00root root 0000000 0000000 #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.h 0000664 0000000 0000000 00000000413 15004542521 0016603 0 ustar 00root root 0000000 0000000 #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.c 0000664 0000000 0000000 00000001204 15004542521 0017110 0 ustar 00root root 0000000 0000000 #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.c 0000664 0000000 0000000 00000025520 15004542521 0017202 0 ustar 00root root 0000000 0000000 /* 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.h 0000664 0000000 0000000 00000000751 15004542521 0017206 0 ustar 00root root 0000000 0000000 #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.c 0000664 0000000 0000000 00000001473 15004542521 0017140 0 ustar 00root root 0000000 0000000 #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.c 0000664 0000000 0000000 00000002527 15004542521 0017505 0 ustar 00root root 0000000 0000000 #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/ 0000775 0000000 0000000 00000000000 15004542521 0015754 5 ustar 00root root 0000000 0000000 opengnb-ver1.6.0.a/libs/hash/murmurhash.c 0000664 0000000 0000000 00000001363 15004542521 0020316 0 ustar 00root root 0000000 0000000 #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/ 0000775 0000000 0000000 00000000000 15004542521 0017017 5 ustar 00root root 0000000 0000000 opengnb-ver1.6.0.a/libs/libnatpmp/LICENSE 0000664 0000000 0000000 00000002676 15004542521 0020037 0 ustar 00root root 0000000 0000000 Copyright (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.h 0000664 0000000 0000000 00000000717 15004542521 0020757 0 ustar 00root root 0000000 0000000 #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.c 0000664 0000000 0000000 00000044015 15004542521 0021330 0 ustar 00root root 0000000 0000000 /* $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.h 0000664 0000000 0000000 00000003653 15004542521 0021340 0 ustar 00root root 0000000 0000000 /* $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.c 0000664 0000000 0000000 00000024531 15004542521 0020467 0 ustar 00root root 0000000 0000000 /* $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.h 0000664 0000000 0000000 00000016266 15004542521 0020502 0 ustar 00root root 0000000 0000000 /* $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.c 0000664 0000000 0000000 00000004250 15004542521 0022363 0 ustar 00root root 0000000 0000000 /* $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.h 0000664 0000000 0000000 00000003367 15004542521 0022400 0 ustar 00root root 0000000 0000000 /* $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/ 0000775 0000000 0000000 00000000000 15004542521 0017033 5 ustar 00root root 0000000 0000000 opengnb-ver1.6.0.a/libs/miniupnpc/LICENSE 0000664 0000000 0000000 00000002710 15004542521 0020040 0 ustar 00root root 0000000 0000000 MiniUPnPc
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/README 0000664 0000000 0000000 00000006612 15004542521 0017720 0 ustar 00root root 0000000 0000000 Project: 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/VERSION 0000664 0000000 0000000 00000000004 15004542521 0020075 0 ustar 00root root 0000000 0000000 2.1
opengnb-ver1.6.0.a/libs/miniupnpc/codelength.h 0000664 0000000 0000000 00000003025 15004542521 0021320 0 ustar 00root root 0000000 0000000 /* $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.c 0000664 0000000 0000000 00000016607 15004542521 0022445 0 ustar 00root root 0000000 0000000 /* $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.h 0000664 0000000 0000000 00000001203 15004542521 0022434 0 ustar 00root root 0000000 0000000 /* $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.c 0000664 0000000 0000000 00000011016 15004542521 0022131 0 ustar 00root root 0000000 0000000 /* $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.h 0000664 0000000 0000000 00000003135 15004542521 0022141 0 ustar 00root root 0000000 0000000 /* $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.c 0000664 0000000 0000000 00000006702 15004542521 0021023 0 ustar 00root root 0000000 0000000 /* $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.h 0000664 0000000 0000000 00000001034 15004542521 0021021 0 ustar 00root root 0000000 0000000 /* $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.c 0000664 0000000 0000000 00000062651 15004542521 0021202 0 ustar 00root root 0000000 0000000 /* $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.h 0000664 0000000 0000000 00000003140 15004542521 0021173 0 ustar 00root root 0000000 0000000 /* $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.c 0000664 0000000 0000000 00000050506 15004542521 0021207 0 ustar 00root root 0000000 0000000 /* $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\">"
"" SERVICEPREFIX ":%s>"
"" SOAPPREFIX ":Body>" SOAPPREFIX ":Envelope>"
"\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, ">" SOAPPREFIX ":Body>" SOAPPREFIX ":Envelope>\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.h 0000664 0000000 0000000 00000011776 15004542521 0021222 0 ustar 00root root 0000000 0000000 /* $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.h 0000664 0000000 0000000 00000001060 15004542521 0023045 0 ustar 00root root 0000000 0000000 #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.h 0000664 0000000 0000000 00000001770 15004542521 0023242 0 ustar 00root root 0000000 0000000 /* $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.h 0000664 0000000 0000000 00000001263 15004542521 0022622 0 ustar 00root root 0000000 0000000 /* $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.in 0000664 0000000 0000000 00000001265 15004542521 0023231 0 ustar 00root root 0000000 0000000 /* $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.h 0000664 0000000 0000000 00000001142 15004542521 0022271 0 ustar 00root root 0000000 0000000 /* $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.c 0000664 0000000 0000000 00000040566 15004542521 0021035 0 ustar 00root root 0000000 0000000 /* $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.h 0000664 0000000 0000000 00000001262 15004542521 0021030 0 ustar 00root root 0000000 0000000 /* $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.h 0000664 0000000 0000000 00000000704 15004542521 0022562 0 ustar 00root root 0000000 0000000 /* $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.c 0000664 0000000 0000000 00000013232 15004542521 0020655 0 ustar 00root root 0000000 0000000 /* $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.h 0000664 0000000 0000000 00000002233 15004542521 0020661 0 ustar 00root root 0000000 0000000 /* $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.c 0000664 0000000 0000000 00000007343 15004542521 0022617 0 ustar 00root root 0000000 0000000 /* $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.h 0000664 0000000 0000000 00000003446 15004542521 0022624 0 ustar 00root root 0000000 0000000 /* $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.c 0000664 0000000 0000000 00000005665 15004542521 0021467 0 ustar 00root root 0000000 0000000 /* $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.h 0000664 0000000 0000000 00000001355 15004542521 0021464 0 ustar 00root root 0000000 0000000 /* $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.c 0000664 0000000 0000000 00000104533 15004542521 0021711 0 ustar 00root root 0000000 0000000 /* $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.h 0000664 0000000 0000000 00000032416 15004542521 0021716 0 ustar 00root root 0000000 0000000 /* $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.c 0000664 0000000 0000000 00000001071 15004542521 0020657 0 ustar 00root root 0000000 0000000 /* $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.h 0000664 0000000 0000000 00000001325 15004542521 0020666 0 ustar 00root root 0000000 0000000 /* $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.c 0000664 0000000 0000000 00000004363 15004542521 0021424 0 ustar 00root root 0000000 0000000 /* $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.h 0000664 0000000 0000000 00000001160 15004542521 0021421 0 ustar 00root root 0000000 0000000 /* $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.c 0000664 0000000 0000000 00000010655 15004542521 0022277 0 ustar 00root root 0000000 0000000 /* $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.h 0000664 0000000 0000000 00000002521 15004542521 0022275 0 ustar 00root root 0000000 0000000 /* $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/ 0000775 0000000 0000000 00000000000 15004542521 0016672 5 ustar 00root root 0000000 0000000 opengnb-ver1.6.0.a/libs/protocol/network_protocol.h 0000664 0000000 0000000 00000004114 15004542521 0022455 0 ustar 00root root 0000000 0000000 #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/ 0000775 0000000 0000000 00000000000 15004542521 0017305 5 ustar 00root root 0000000 0000000 opengnb-ver1.6.0.a/libs/tap-windows/tap-windows.h 0000664 0000000 0000000 00000006217 15004542521 0021740 0 ustar 00root root 0000000 0000000 /*
* 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/ 0000775 0000000 0000000 00000000000 15004542521 0016355 5 ustar 00root root 0000000 0000000 opengnb-ver1.6.0.a/libs/wintun/wintun.h 0000664 0000000 0000000 00000024172 15004542521 0020060 0 ustar 00root root 0000000 0000000 /* 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/ 0000775 0000000 0000000 00000000000 15004542521 0015771 5 ustar 00root root 0000000 0000000 opengnb-ver1.6.0.a/libs/zlib/LICENSE 0000664 0000000 0000000 00000001752 15004542521 0017003 0 ustar 00root root 0000000 0000000 Copyright 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.c 0000664 0000000 0000000 00000011544 15004542521 0017376 0 ustar 00root root 0000000 0000000 /* 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.c 0000664 0000000 0000000 00000237503 15004542521 0017553 0 ustar 00root root 0000000 0000000 /* 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.h 0000664 0000000 0000000 00000033331 15004542521 0017551 0 ustar 00root root 0000000 0000000 /* 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.h 0000664 0000000 0000000 00000015024 15004542521 0017467 0 ustar 00root root 0000000 0000000 /* 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.c 0000664 0000000 0000000 00000031174 15004542521 0017575 0 ustar 00root root 0000000 0000000 /* 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.h 0000664 0000000 0000000 00000000646 15004542521 0017602 0 ustar 00root root 0000000 0000000 /* 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.h 0000664 0000000 0000000 00000014274 15004542521 0017746 0 ustar 00root root 0000000 0000000 /* 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.c 0000664 0000000 0000000 00000154337 15004542521 0017574 0 ustar 00root root 0000000 0000000 /* 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.h 0000664 0000000 0000000 00000015033 15004542521 0017566 0 ustar 00root root 0000000 0000000 /* 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.c 0000664 0000000 0000000 00000031340 15004542521 0017755 0 ustar 00root root 0000000 0000000 /* 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.h 0000664 0000000 0000000 00000005550 15004542521 0017766 0 ustar 00root root 0000000 0000000 /* 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.c 0000664 0000000 0000000 00000117751 15004542521 0017273 0 ustar 00root root 0000000 0000000 /* 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.h 0000664 0000000 0000000 00000020430 15004542521 0017263 0 ustar 00root root 0000000 0000000 /* 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.h 0000664 0000000 0000000 00000040164 15004542521 0017266 0 ustar 00root root 0000000 0000000 /* 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.h 0000664 0000000 0000000 00000275075 15004542521 0017122 0 ustar 00root root 0000000 0000000 /* 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.c 0000664 0000000 0000000 00000016013 15004542521 0017305 0 ustar 00root root 0000000 0000000 /* 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.h 0000664 0000000 0000000 00000015025 15004542521 0017314 0 ustar 00root root 0000000 0000000 /* 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/ 0000775 0000000 0000000 00000000000 15004542521 0015567 5 ustar 00root root 0000000 0000000 opengnb-ver1.6.0.a/scripts/opengnb@.service 0000664 0000000 0000000 00000003701 15004542521 0020702 0 ustar 00root root 0000000 0000000 #########################
#(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/ 0000775 0000000 0000000 00000000000 15004542521 0014667 5 ustar 00root root 0000000 0000000 opengnb-ver1.6.0.a/src/Darwin/ 0000775 0000000 0000000 00000000000 15004542521 0016113 5 ustar 00root root 0000000 0000000 opengnb-ver1.6.0.a/src/Darwin/gnb_drv_darwin.c 0000775 0000000 0000000 00000023470 15004542521 0021255 0 ustar 00root root 0000000 0000000 /*
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/ 0000775 0000000 0000000 00000000000 15004542521 0015436 5 ustar 00root root 0000000 0000000 opengnb-ver1.6.0.a/src/cli/gnb.c 0000775 0000000 0000000 00000035053 15004542521 0016361 0 ustar 00root root 0000000 0000000 /*
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