Imported Upstream version 0.3 origin/upstream v0.3
authorMichael Prokop <mika@grml.org>
Fri, 29 May 2009 19:37:22 +0000 (21:37 +0200)
committerMichael Prokop <mika@grml.org>
Fri, 29 May 2009 19:37:22 +0000 (21:37 +0200)
49 files changed:
AUTHORS [new file with mode: 0644]
ChangeLog [new file with mode: 0644]
LICENSE [new file with mode: 0644]
README [new file with mode: 0644]
doc/Makefile [new file with mode: 0644]
doc/uanytun.8.txt [new file with mode: 0644]
etc/init.d/uanytun [new file with mode: 0755]
etc/uanytun/autostart [new file with mode: 0644]
etc/uanytun/client1/config [new file with mode: 0644]
etc/uanytun/client1/post-up.sh [new file with mode: 0755]
etc/uanytun/client2/config [new file with mode: 0644]
etc/uanytun/client2/post-up.sh [new file with mode: 0755]
etc/uanytun/client3/config [new file with mode: 0644]
etc/uanytun/client3/post-up.sh [new file with mode: 0755]
etc/uanytun/p2p-a/config [new file with mode: 0644]
etc/uanytun/p2p-b/config [new file with mode: 0644]
src/Makefile [new file with mode: 0644]
src/auth_algo.c [new file with mode: 0644]
src/auth_algo.h [new file with mode: 0644]
src/bsd/tun.c [new file with mode: 0644]
src/cipher.c [new file with mode: 0644]
src/cipher.h [new file with mode: 0644]
src/configure [new file with mode: 0755]
src/daemon.h [new file with mode: 0644]
src/datatypes.h [new file with mode: 0644]
src/encrypted_packet.c [new file with mode: 0644]
src/encrypted_packet.h [new file with mode: 0644]
src/key_derivation.c [new file with mode: 0644]
src/key_derivation.h [new file with mode: 0644]
src/linux/tun.c [new file with mode: 0644]
src/log.c [new file with mode: 0644]
src/log.h [new file with mode: 0644]
src/log_targets.h [new file with mode: 0644]
src/options.c [new file with mode: 0644]
src/options.h [new file with mode: 0644]
src/plain_packet.c [new file with mode: 0644]
src/plain_packet.h [new file with mode: 0644]
src/seq_window.c [new file with mode: 0644]
src/seq_window.h [new file with mode: 0644]
src/sig_handler.c [new file with mode: 0644]
src/sig_handler.h [new file with mode: 0644]
src/string_list.c [new file with mode: 0644]
src/string_list.h [new file with mode: 0644]
src/sysexec.h [new file with mode: 0644]
src/tun.h [new file with mode: 0644]
src/tun_helper.h [new file with mode: 0644]
src/uanytun.c [new file with mode: 0644]
src/udp.c [new file with mode: 0644]
src/udp.h [new file with mode: 0644]

diff --git a/AUTHORS b/AUTHORS
new file mode 100644 (file)
index 0000000..0a39671
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1 @@
+Christian Pointner <equinox@anytun.org>
diff --git a/ChangeLog b/ChangeLog
new file mode 100644 (file)
index 0000000..2034049
--- /dev/null
+++ b/ChangeLog
@@ -0,0 +1,35 @@
+2009.05.01 -- Version 0.3
+
+* updated to new protocol specification (extended label and crypto role)
+  Mind that due this protocol changes this version is incompatible to older 
+  version of anytun and uanytun
+* the auth tag length can now be configured
+* added extended logging support (syslog, file, stdout and stderr)
+* changed -n|--ifconfig parameter to new behavior
+  tun and tap devices now use the same syntax
+* improved tap device handling on OpenBSD
+* fixed name resolution bug
+* fixed ipv6 addrlen bug
+* fixed packet length errors
+* fixed device type detection bug
+* dropping privileges is now possible wihtout chroot
+* some code cleanup
+
+2009.01.14 -- Version 0.2.1
+
+* fixed bug which prevents the daemon from using the right cipher
+  key when using a key derivation rate other than 1
+       
+2009.01.11 -- Version 0.2
+
+* added crypto support using libgcrypt or openssl
+* added new passphrase option to generate master key and or salt
+* cleaned up and improved build system
+* some code cleanup
+
+
+2008.12.31 -- Version 0.1
+
+* Initial release.
+* IPv4, IPv6 and Ethernet tunnel over UDP, without crypto.
+* tested on Linux and OpenBSD
diff --git a/LICENSE b/LICENSE
new file mode 100644 (file)
index 0000000..72582db
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,707 @@
+/*
+ *  uAnytun
+ *
+ *  uAnytun is a tiny implementation of SATP. Unlike Anytun which is a full
+ *  featured implementation uAnytun has no support for multiple connections
+ *  or synchronisation. It is a small single threaded implementation intended
+ *  to act as a client on small platforms.
+ *  The secure anycast tunneling protocol (satp) defines a protocol used
+ *  for communication between any combination of unicast and anycast
+ *  tunnel endpoints.  It has less protocol overhead than IPSec in Tunnel
+ *  mode and allows tunneling of every ETHER TYPE protocol (e.g.
+ *  ethernet, ip, arp ...). satp directly includes cryptography and
+ *  message authentication based on the methodes used by SRTP.  It is
+ *  intended to deliver a generic, scaleable and secure solution for
+ *  tunneling and relaying of packets of any protocol.
+ *  
+ *
+ *  Copyright (C) 2007-2008 Christian Pointner <equinox@anytun.org>
+ *
+ *  This file is part of uAnytun.
+ *
+ *  uAnytun is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 3 as
+ *  published by the Free Software Foundation.
+ *
+ *  uAnytun 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 uAnytun. If not, see <http://www.gnu.org/licenses/>.
+ */
+                    GNU GENERAL PUBLIC LICENSE
+                       Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ 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.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 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 <http://www.gnu.org/licenses/>.
+
+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:
+
+    <program>  Copyright (C) <year>  <name of author>
+    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
+<http://www.gnu.org/licenses/>.
+
+  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
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
diff --git a/README b/README
new file mode 100644 (file)
index 0000000..a5bc7ee
--- /dev/null
+++ b/README
@@ -0,0 +1,86 @@
+Dependencies
+============
+
+uAnytun can be built by using either libgcrypt or the openssl-crypto library. 
+The latter is more performant in most cases but there are some license 
+issues when using this library. It also needs more space when installed.
+
+Linux
+-----
+
+using libgcrypt:
+ build-essential
+ libgcrypt11-dev
+
+using ssl crypto library:
+
+ build-essential
+ libssl-dev
+
+
+OpenBSD/FreeBSD
+---------------
+
+using libgcrypt:
+
+ gmake
+ libgcrypt
+ libgpg-error
+
+using ssl crypto library:
+
+ gmake
+
+
+Installation
+============
+
+Getting the source via subversion:
+----------------------------------
+svn co https://svn.chaos-at-home.org/uanytun/trunk uanytun
+
+Building from source
+--------------------
+
+using libgcrypt:
+
+# cd src
+# ./configure
+# make
+
+using ssl crypto library:
+
+# cd src
+# ./configure --use-ssl-crypto
+# make
+
+
+Notes: 
+  - try './configure --help' for further information
+  - if using openssl pre 0.9.8 you have to disable passphrase
+    because openssl had no SHA256 implementation prior to this
+    version
+  - on OpenBSD/FreeBSD you have to use gmake instead of make
+
+
+Installing
+----------
+
+# sudo make install
+
+This will install anytun under the --prefix defined with configure.
+It also creates a user with name --username  with home --userhome 
+which can be changed by configure as well.
+
+Uninstalling
+------------
+
+# sudo make remove
+
+This removes everytthing except for the config files
+
+# sudo make purge
+
+This also removes the config files and deletes the user and it's
+home directory.
diff --git a/doc/Makefile b/doc/Makefile
new file mode 100644 (file)
index 0000000..f49deda
--- /dev/null
@@ -0,0 +1,43 @@
+##
+##  uAnytun
+##
+##  uAnytun is a tiny implementation of SATP. Unlike Anytun which is a full
+##  featured implementation uAnytun has no support for multiple connections
+##  or synchronisation. It is a small single threaded implementation intended
+##  to act as a client on small platforms.
+##  The secure anycast tunneling protocol (satp) defines a protocol used
+##  for communication between any combination of unicast and anycast
+##  tunnel endpoints.  It has less protocol overhead than IPSec in Tunnel
+##  mode and allows tunneling of every ETHER TYPE protocol (e.g.
+##  ethernet, ip, arp ...). satp directly includes cryptography and
+##  message authentication based on the methodes used by SRTP.  It is
+##  intended to deliver a generic, scaleable and secure solution for
+##  tunneling and relaying of packets of any protocol.
+##  
+##
+##  Copyright (C) 2007-2008 Christian Pointner <equinox@anytun.org>
+##
+##  This file is part of uAnytun.
+##
+##  uAnytun is free software: you can redistribute it and/or modify
+##  it under the terms of the GNU General Public License version 3 as
+##  published by the Free Software Foundation.
+##
+##  uAnytun 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 uAnytun. If not, see <http://www.gnu.org/licenses/>.
+##
+
+all: manpage
+
+uanytun.8: uanytun.8.txt
+       a2x -f manpage uanytun.8.txt
+
+manpage: uanytun.8
+
+clean:
+       rm -f uanytun.8 uanytun.8.xml
diff --git a/doc/uanytun.8.txt b/doc/uanytun.8.txt
new file mode 100644 (file)
index 0000000..311c54a
--- /dev/null
@@ -0,0 +1,370 @@
+uanytun(8)
+==========
+
+NAME
+----
+uanytun - micro anycast tunneling daemon
+
+SYNOPSIS
+--------
+
+*uanytun*
+[ *-h|--help* ]
+[ *-D|--nodaemonize* ]
+[ *-u|--username* <username> ]
+[ *-g|--groupname* <groupname> ]
+[ *-C|--chroot* <path> ]
+[ *-P|--write-pid* <filename> ]
+[ *-L|--log* <target>:<level>[,<param1>[,<param2>[..]]] ]
+[ *-i|--interface* <ip-address> ]
+[ *-p|--port* <port> ]
+[ *-r|--remote-host* <hostname|ip> ]
+[ *-o|--remote-port* <port> ]
+[ *-4|--ipv4-only* ]
+[ *-6|--ipv6-only* ]
+[ *-d|--dev* <name> ]
+[ *-t|--type* <tun|tap> ]
+[ *-n|--ifconfig* <local>/<prefix> ]
+[ *-x|--post-up-script* <script> ]
+[ *-m|--mux* <mux-id> ]
+[ *-s|--sender-id* <sender id> ]
+[ *-w|--window-size* <window size> ]
+[ *-k|--kd-prf* <kd-prf type> ]
+[ *-e|--role <role>* ]
+[ *-E|--passphrase* <pass phrase> ]
+[ *-K|--key* <master key> ]
+[ *-A|--salt* <master salt> ]
+[ *-c|--cipher* <cipher type> ]
+[ *-a|--auth-algo* <algo type> ]
+[ *-b|--auth-tag-length* <length> ]
+
+DESCRIPTION
+-----------
+
+*uAnytun* is a tiny implementation of the Secure Anycast Tunneling Protocol
+(SATP). It provides a complete VPN solution similar to OpenVPN or
+IPsec in tunnel mode. The main difference is that anycast enables the
+setup of tunnels between an arbitrary combination of anycast, unicast
+and multicast hosts. Unlike Anytun which is a full featured implementation 
+uAnytun has no support for multiple connections or synchronisation. It is a 
+small single threaded implementation intended to act as a client on small 
+platforms.
+
+OPTIONS
+-------
+
+*uAnytun* has been designed as a peer to peer application, so there is
+no difference between client and server. The following options can be
+passed to the daemon:
+
+-D|--nodaemonize
+~~~~~~~~~~~~~~~~
+
+This option instructs *uAnytun* to run in foreground
+instead of becoming a daemon which is the default.
+
+-u|--username <username>
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+run as this user. If no group is specified (*-g*) the default group of 
+the user is used. The default is to not drop privileges.
+
+-g|--groupname <groupname>
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+run as this group. If no username is specified (*-u*) this gets ignored.
+The default is to not drop privileges.
+
+-C|--chroot <path>
+~~~~~~~~~~~~~~~~~~
+
+Instruct *uAnytun* to run in a chroot jail. The default is 
+to not run in chroot.
+
+-P|--write-pid <filename>
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Instruct *uAnytun* to write it's pid to this file. The default is 
+to not create a pid file.
+
+-L|--log <target>:<level>[,<param1>[,<param2>[..]]]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+add log target to logging system. This can be invoked several times
+in order to log to different targets at the same time. Every target 
+hast its own log level which is a number between 0 and 5. Where 0 means
+disabling log and 5 means debug messages are enabled.
+
+The following targets are supported:
+
+* *syslog* - log to syslog daemon, parameters <level>[,<logname>[,<facility>]]
+* *file* - log to file, parameters <level>[,<path>]
+* *stdout* - log to standard output, parameters <level>
+* *stderr* - log to standard error, parameters <level> 
+
+The file target can be used more the once with different levels.
+If no target is provided at the command line a single target with the 
+following config is added:
+
+*syslog:3,uanytun,daemon*
+
+
+-i|--interface <ip address>
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+This IP address is used as the sender address for outgoing
+packets. The default is to not use a special inteface and just
+bind on all interfaces.
+
+-p|--port <port>
+~~~~~~~~~~~~~~~~
+
+local port to bind to
+
+The local UDP port that is used to send and receive the
+payload data. The two tunnel endpoints can use different
+ports. default: 4444
+
+-r|--remote-host <hostname|ip>
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+remote host
+
+This option can be used to specify the remote tunnel
+endpoint. In case of anycast tunnel endpoints, the
+anycast IP address has to be used. If you do not specify
+an address, it is automatically determined after receiving
+the first data packet.
+
+-o|--remote-port <port>
+~~~~~~~~~~~~~~~~~~~~~~~
+
+remote port
+
+The UDP port used for payload data by the remote host
+(specified with -p on the remote host). If you do not specify
+a port, it is automatically determined after receiving
+the first data packet.
+
+-4|--ipv4-only
+~~~~~~~~~~~~~~
+
+Resolv to IPv4 addresses only. The default is to resolv both
+IPv4 and IPv6 addresses.
+
+-6|--ipv6-only
+~~~~~~~~~~~~~~
+
+Resolv to IPv6 addresses only. The default is to resolv both
+IPv4 and IPv6 addresses.
+
+-d|--dev <name>
+~~~~~~~~~~~~~~~
+
+device name
+
+By default, tapN is used for Ethernet tunnel interfaces,
+and tunN for IP tunnels, respectively. This option can
+be used to manually override these defaults.
+
+-t|--type <tun|tap>
+~~~~~~~~~~~~~~~~~~~
+
+device type
+
+Type of the tunnels to create. Use tap for Ethernet
+tunnels, tun for IP tunnels.
+
+-n|--ifconfig <local>/<prefix>
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+*<local>* the local IP address for the tun/tap device
+
+*<prefix>* the prefix length of the network
+
+The local IP address and prefix length. The remote tunnel endpoint
+has to use a different IP address in the same subnet.
+
+-x|--post-up-script <script>
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+This option instructs *uAnytun* to run this script after the interface 
+is created. By default no script will be executed.
+
+-m|--mux <mux-id>
+~~~~~~~~~~~~~~~~~
+
+the multiplex id to use. default: 0
+
+-s|--sender-id  <sender id>
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Each anycast tunnel endpoint needs a unique sender id
+(1, 2, 3, ...). It is needed to distinguish the senders
+in case of replay attacks. As *uAnytun* does not support 
+synchronisation it can't be used as an anycast endpoint therefore 
+this option is quite useless but implemented for compability 
+reasons. default: 0
+
+-w|--window-size <window size>
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+seqence window size
+
+Sometimes, packets arrive out of order on the receiver
+side. This option defines the size of a list of received
+packets' sequence numbers. If, according to this list,
+a received packet has been previously received or has
+been transmitted in the past, and is therefore not in
+the list anymore, this is interpreted as a replay attack
+and the packet is dropped. A value of 0 deactivates this
+list and, as a consequence, the replay protection employed
+by filtering packets according to their secuence number.
+By default the sequence window is disabled and therefore a
+window size of 0 is used.
+
+-k|--kd--prf <kd-prf type>
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+key derivation pseudo random function.
+
+The pseudo random function which is used for calculating the 
+session keys and session salt.
+
+Possible values:
+
+* *null* - no random function, keys and salt are set to 0..00
+* *aes-ctr* - AES in counter mode with 128 Bits, default value
+* *aes-ctr-128* - AES in counter mode with 128 Bits
+* *aes-ctr-192* - AES in counter mode with 192 Bits
+* *aes-ctr-256* - AES in counter mode with 256 Bits
+
+-e|--role <role>
+~~~~~~~~~~~~~~~~
+
+SATP uses different session keys for inbound and outbound traffic. The
+role parameter is used to determine which keys to use for outbound or
+inbound packets. On both sides of a vpn connection different roles have 
+to be used. Possible values are *left* and *right*. You may also use 
+*alice* or *server* as a replacement for *left* and *bob* or *client* as 
+a replacement for *right*. By default *left* is used.
+
+-E|--passphrase <pass phrase>
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+This passphrase is used to generate the master key and master salt.
+For the master key the last n bits of the SHA256 digest of the 
+passphrase (where n is the length of the master key in bits) is used. 
+The master salt gets generated with the SHA1 digest. 
+You may force a specific key and or salt by using *--key* and *--salt*.
+
+-K|--key <master key>
+~~~~~~~~~~~~~~~~~~~~~
+
+master key to use for key derivation
+
+Master key in hexadecimal notation, eg
+01a2b3c4d5e6f708a9b0cadbecfd0fa1, with a mandatory length
+of 32, 48 or 64 characters (128, 192 or 256 bits).
+
+-A|--salt <master salt>
+~~~~~~~~~~~~~~~~~~~~~~~
+
+master salt to use for key derivation
+
+Master salt in hexadecimal notation, eg
+01a2b3c4d5e6f708a9b0cadbecfd, with a mandatory length
+of 28 characters (14 bytes).
+
+-c|--cipher <cipher type>
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+payload encryption algorithm
+
+Encryption algorithm used for encrypting the payload
+
+Possible values:
+
+* *null* - no encryption
+* *aes-ctr* - AES in counter mode with 128 Bits, default value
+* *aes-ctr-128* - AES in counter mode with 128 Bits
+* *aes-ctr-192* - AES in counter mode with 192 Bits
+* *aes-ctr-256* - AES in counter mode with 256 Bits
+
+-a|--auth-algo <algo type>
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+message authentication algorithm
+
+This option sets the message authentication algorithm.
+
+Possible values:
+
+* *null* - no message authentication
+* *sha1* - HMAC-SHA1, default value
+
+If HMAC-SHA1 is used, the packet length is increased. The additional bytes 
+contain the authentication data. see *-b|--auth-tag-length* for more info.
+
+-b|--auth-tag-length <length>
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The number of bytes to use for the auth tag. This value defaults to 10 bytes 
+unless the *null* auth algo is used in which case it defaults to 0. 
+
+EXAMPLES
+--------
+
+P2P Setup between two unicast enpoints:
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Host A:
+^^^^^^^
+
+uanytun -r hostb.example.com -t tun -n 192.168.123.1/30 -c aes-ctr-256 -k aes-ctr-256 \
+        -E have_a_very_safe_and_productive_day -e left
+
+Host B:
+^^^^^^^
+uanytun -r hosta.example.com -t tun -n 192.168.123.2/30 -c aes-ctr-256 -k aes-ctr-256 \
+        -E have_a_very_safe_and_productive_day -e right
+
+
+One unicast and one anycast tunnel endpoint:
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Unicast tunnel endpoint:
+^^^^^^^^^^^^^^^^^^^^^^^^
+
+uanytun -r anycast.anytun.org -d anytun0 -t tun -n 192.0.2.2/30 -a null -c null -w 0 -e client
+
+Anycast tunnel endpoints:
+^^^^^^^^^^^^^^^^^^^^^^^^^
+As *uAnytun* can't work as an anycast endpoint it can't be used for this purpose. You
+have to use *anytun* for that job.
+
+
+BUGS
+----
+Most likely there are some bugs in *uAnytun*. If you find a bug, please let
+the developers know at uanytun@anytun.org. Of course, patches are preferred.
+
+AUTHORS
+-------
+
+Christian Pointner <equinox@anytun.org>
+
+RESOURCES
+---------
+
+Main web site: http://www.anytun.org/
+
+
+COPYING
+-------
+
+Copyright \(C) 2008-2009 Christian Pointner. This  program is  free 
+software; you can redistribute it and/or modify it under the terms 
+of the GNU General Public License version 3 as published by the 
+Free Software Foundation.
+
diff --git a/etc/init.d/uanytun b/etc/init.d/uanytun
new file mode 100755 (executable)
index 0000000..781e809
--- /dev/null
@@ -0,0 +1,135 @@
+#! /bin/sh
+### BEGIN INIT INFO
+# Provides:          uanytun
+# Required-Start:    $network $named $syslog
+# Required-Stop:     
+# Default-Start:     2 3 4 5
+# Default-Stop:      0 1 6
+# Short-Description: Start anycast tunneling daemon at boot time
+# Description:       Enables networking over vpn tunnel interfaces
+### END INIT INFO
+PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
+DAEMON=/usr/sbin/uanytun
+CONFIG_DIR=/etc/uanytun
+NAME=uanytun
+DESC=uanytun
+
+test -x $DAEMON || exit 0
+
+# Include uanytun defaults if available
+if [ -f /etc/default/uanytun ] ; then
+  . /etc/default/uanytun
+fi
+
+start_vpn () {
+  STATUS="OK"
+  if [ -f $CONFIG_DIR/$NAME/config ] ; then
+    POSTUP=''
+    test -f  $CONFIG_DIR/$NAME/post-up.sh && POSTUP="-x $CONFIG_DIR/$NAME/post-up.sh"
+    CHROOTDIR=`grep '^chroot' < $CONFIG_DIR/$NAME/config | sed 's/chroot\s*//'`
+    if [ -n "$CHROOTDIR" ] ; then
+      test -d $CHROOTDIR || mkdir -p $CHROOTDIR
+    fi
+    DAEMONARG=`sed 's/#.*//' < $CONFIG_DIR/$NAME/config | grep -e '\w' | sed  's/^/--/' | tr '\n' ' '`
+    $DAEMON --write-pid /var/run/uanytun.$NAME.pid $POSTUP $DAEMONARG || STATUS="FAILED"
+  else
+    STATUS="no config found"
+  fi
+  echo -n "($STATUS)"
+}
+stop_vpn () {
+  kill `cat $PIDFILE` || true
+  rm $PIDFILE
+}
+
+set -e
+case "$1" in
+  start)
+  echo -n "Starting $DESC:"
+  if test -z "$2" ; then
+    if [ -f $CONFIG_DIR/autostart ] ; then
+      for NAME in `sed 's/#.*//'  <  $CONFIG_DIR/autostart | grep -e '\w'`; do
+        echo -n " $NAME"
+        start_vpn
+      done
+    else
+      echo " no config found"
+      exit 1;
+    fi
+  else
+    while shift ; do
+      [ -z "$1" ] && break
+      NAME=$1
+      echo -n " $NAME"
+      start_vpn
+    done
+  fi
+  echo "."
+  ;;
+  stop)
+  echo -n "Stoping $DESC:"
+  if test -z "$2" ; then
+    for PIDFILE in `ls /var/run/uanytun.*.pid 2> /dev/null`; do
+      NAME=`echo $PIDFILE | cut -c18-`
+      NAME=${NAME%%.pid}
+      echo -n " $NAME"
+      stop_vpn
+    done
+  else
+    while shift ; do
+      [ -z "$1" ] && break
+      if test -e /var/run/uanytun.$1.pid ; then
+        PIDFILE=`ls /var/run/uanytun.$1.pid 2> /dev/null`
+        NAME=`echo $PIDFILE | cut -c18-`
+        NAME=${NAME%%.pid}
+        echo -n " $NAME"
+        stop_vpn
+      else
+        echo -n " (failure: No such tunnel is running: $1)"
+      fi
+    done
+  fi
+  echo "."
+  ;;
+  reload)
+  echo -n "Reloading $DESC:"
+  if test -z "$2" ; then
+    for PIDFILE in `ls /var/run/uanytun.*.pid 2> /dev/null`; do
+      NAME=`echo $PIDFILE | cut -c18-`
+      NAME=${NAME%%.pid}
+      echo -n " $NAME"
+      stop_vpn
+      start_vpn
+    done
+  else
+    while shift ; do
+      [ -z "$1" ] && break
+      if test -e /var/run/uanytun.$1.pid ; then
+        PIDFILE=`ls /var/run/uanytun.$1.pid 2> /dev/null`
+        NAME=`echo $PIDFILE | cut -c18-`
+        NAME=${NAME%%.pid}
+        echo -n " $NAME"
+        stop_vpn
+        start_vpn
+      else
+        echo -n " (failure: No such tunnel is running: $1)"
+      fi
+    done
+  fi
+  echo "."
+  ;;
+  restart)
+    SCRIPT=$0
+    shift
+    $SCRIPT stop $*
+    sleep 1
+    $SCRIPT start $*
+  ;;
+  *)
+  N=/etc/init.d/$NAME
+  echo "Usage: $N {start|stop|restart|reload}" >&2
+  exit 1
+  ;;
+esac
+
+exit 0
diff --git a/etc/uanytun/autostart b/etc/uanytun/autostart
new file mode 100644 (file)
index 0000000..f20d7e9
--- /dev/null
@@ -0,0 +1,5 @@
+p2p-a
+#p2p-b
+#client1
+#client2
+#client3
diff --git a/etc/uanytun/client1/config b/etc/uanytun/client1/config
new file mode 100644 (file)
index 0000000..03b0207
--- /dev/null
@@ -0,0 +1,94 @@
+#############################
+## Main options             #
+#############################
+
+role client
+
+## Client ID
+##  (has to be unique for each client)
+mux 1
+
+## device type tun = ip/ipv6, tap = ethernet
+type tun
+
+## payload encryption algorithm
+#cipher null
+#cipher aes-ctr-128
+#cipher aes-ctr-192
+#cipher aes-ctr-256
+cipher aes-ctr
+
+## message authentication algorithm
+#auth-algo null
+auth-algo sha1
+
+##message auth tag length
+#auth-tag-length 10
+
+## Passphrase
+## this is used to generate the crypto-key and salt
+## this should be al least 30 characters
+passphrase Creating_VPN_Tunnels_With_Anytun_Is_Easy
+
+## The remote host and port
+remote-host example.com
+remote-port 4444
+
+#############################
+## Debug options            #
+#############################
+
+## don't run in background
+#nodaemonize
+
+## additional log to standard output with a level of 5
+#log stdout:5
+
+
+#############################
+## Expert options           #
+#############################
+
+## log to syslog with a level of 3
+log syslog:3,uanytun-client1,daemon
+
+## change user and group after init
+username uanytun
+groupname uanytun
+
+## chroot to users home directory
+#chroot /var/run/uanytun
+
+## key derivation pseudo random function
+#kd-prf null
+#kd-prf aes-ctr
+#kd-prf aes-ctr-128
+#kd-prf aes-ctr-192
+#kd-prf aes-ctr-256
+
+## local ip address to bind to (for tunnel data)
+## (if you run an anycast cluster this has to be the anycast ip address)
+#interface <ip-address>
+
+## local port to bind to (for tunnel data)
+## make sure to use a different port for every server and client!
+port 4444
+
+## Device name
+#dev uanytun0
+
+## Automaticaly configure the interface
+##
+## We highly recommend the use of the post up script to do this
+##
+## the address hast to be supplied in CIDR notation
+#ifconfig <local>/<prefix length>
+
+## Manually set encryption key and salt
+## (this replaces the passphrase)
+#key 0123456789ABCDEF0123456789ABCDEF
+#salt 0123456789ABCD0123456789ABCD
+
+## Setting a window size > 0 will enable replay protection
+## This most likely will only work with external rekeying
+#window-size 0
diff --git a/etc/uanytun/client1/post-up.sh b/etc/uanytun/client1/post-up.sh
new file mode 100755 (executable)
index 0000000..574a3e8
--- /dev/null
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+ip link set dev $1 up
+ip link set dev $1 mtu 1400
+ip addr add dev $1 192.168.123.1/24
+ip addr add dev $1 fec0::1/64
+
+# disable ICMP redirects as they don't work within the tunnel
+echo 0 > /proc/sys/net/ipv4/conf/$1/send_redirects
+echo 0 > /proc/sys/net/ipv4/conf/$1/accept_redirects
+
+exit 0
diff --git a/etc/uanytun/client2/config b/etc/uanytun/client2/config
new file mode 100644 (file)
index 0000000..f84bf87
--- /dev/null
@@ -0,0 +1,94 @@
+#############################
+## Main options             #
+#############################
+
+role client
+
+## Client ID
+##  (has to be unique for each client)
+mux 2
+
+## device type tun = ip/ipv6, tap = ethernet
+type tun
+
+## payload encryption algorithm
+#cipher null
+#cipher aes-ctr-128
+#cipher aes-ctr-192
+#cipher aes-ctr-256
+cipher aes-ctr
+
+## message authentication algorithm
+#auth-algo null
+auth-algo sha1
+
+##message auth tag length
+#auth-tag-length 10
+
+## Passphrase
+## this is used to generate the crypto-key and salt
+## this should be al least 30 characters
+passphrase Creating_VPN_Tunnels_With_Anytun_Is_Easy
+
+## The remote host and port
+remote-host example.com
+remote-port 4444
+
+#############################
+## Debug options            #
+#############################
+
+## don't run in background
+#nodaemonize
+
+## additional log to standard output with a level of 5
+#log stdout:5
+
+
+#############################
+## Expert options           #
+#############################
+
+## log to syslog with a level of 3
+log syslog:3,uanytun-client2,daemon
+
+## change user and group after init
+username uanytun
+groupname uanytun
+
+## chroot to users home directory
+#chroot /var/run/uanytun
+
+## key derivation pseudo random function
+#kd-prf null
+#kd-prf aes-ctr
+#kd-prf aes-ctr-128
+#kd-prf aes-ctr-192
+#kd-prf aes-ctr-256
+
+## local ip address to bind to (for tunnel data)
+## (if you run an anycast cluster this has to be the anycast ip address)
+#interface <ip-address>
+
+## local port to bind to (for tunnel data)
+## make sure to use a different port for every server and client!
+port 4444
+
+## Device name
+#dev uanytun0
+
+## Automaticaly configure the interface
+##
+## We highly recommend the use of the post up script to do this
+##
+## the address hast to be supplied in CIDR notation
+#ifconfig <local>/<prefix length>
+
+## Manually set encryption key and salt
+## (this replaces the passphrase)
+#key 2123456789ABCDEF0123456789ABCDEF
+#salt 2123456789ABCD0123456789ABCD
+
+## Setting a window size > 0 will enable replay protection
+## This most likely will only work with external rekeying
+#window-size 0
diff --git a/etc/uanytun/client2/post-up.sh b/etc/uanytun/client2/post-up.sh
new file mode 100755 (executable)
index 0000000..b65cb0b
--- /dev/null
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+ip link set dev $1 up
+ip link set dev $1 mtu 1400
+ip addr add dev $1 192.168.123.2/24
+ip addr add dev $1 fec0::2/64
+
+# disable ICMP redirects as they don't work within the tunnel
+echo 0 > /proc/sys/net/ipv4/conf/$1/send_redirects
+echo 0 > /proc/sys/net/ipv4/conf/$1/accept_redirects
+
+exit 0
diff --git a/etc/uanytun/client3/config b/etc/uanytun/client3/config
new file mode 100644 (file)
index 0000000..ba6e35c
--- /dev/null
@@ -0,0 +1,94 @@
+#############################
+## Main options             #
+#############################
+
+role client
+
+## Client ID
+##  (has to be unique for each client)
+mux 3
+
+## device type tun = ip/ipv6, tap = ethernet
+type tun
+
+## payload encryption algorithm
+#cipher null
+#cipher aes-ctr-128
+#cipher aes-ctr-192
+#cipher aes-ctr-256
+cipher aes-ctr
+
+## message authentication algorithm
+#auth-algo null
+auth-algo sha1
+
+##message auth tag length
+#auth-tag-length 10
+
+## Passphrase
+## this is used to generate the crypto-key and salt
+## this should be al least 30 characters
+passphrase Creating_VPN_Tunnels_With_Anytun_Is_Easy
+
+## The remote host and port
+remote-host example.com
+remote-port 4444
+
+#############################
+## Debug options            #
+#############################
+
+## don't run in background
+#nodaemonize
+
+## additional log to standard output with a level of 5
+#log stdout:5
+
+
+#############################
+## Expert options           #
+#############################
+
+## log to syslog with a level of 3
+log syslog:3,uanytun-client3,daemon
+
+## change user and group after init
+username uanytun
+groupname uanytun
+
+## chroot to users home directory
+#chroot /var/run/uanytun
+
+## key derivation pseudo random function
+#kd-prf null
+#kd-prf aes-ctr
+#kd-prf aes-ctr-128
+#kd-prf aes-ctr-192
+#kd-prf aes-ctr-256
+
+## local ip address to bind to (for tunnel data)
+## (if you run an anycast cluster this has to be the anycast ip address)
+#interface <ip-address>
+
+## local port to bind to (for tunnel data)
+## make sure to use a different port for every server and client!
+port 4444
+
+## Device name
+#dev uanytun0
+
+## Automaticaly configure the interface
+##
+## We highly recommend the use of the post up script to do this
+##
+## the address hast to be supplied in CIDR notation
+#ifconfig <local>/<prefix length>
+
+## Manually set encryption key and salt
+## (this replaces the passphrase)
+#key 3123456789ABCDEF0123456789ABCDEF
+#salt 3123456789ABCD0123456789ABCD
+
+## Setting a window size > 0 will enable replay protection
+## This most likely will only work with external rekeying
+#window-size 0
diff --git a/etc/uanytun/client3/post-up.sh b/etc/uanytun/client3/post-up.sh
new file mode 100755 (executable)
index 0000000..b65cb0b
--- /dev/null
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+ip link set dev $1 up
+ip link set dev $1 mtu 1400
+ip addr add dev $1 192.168.123.2/24
+ip addr add dev $1 fec0::2/64
+
+# disable ICMP redirects as they don't work within the tunnel
+echo 0 > /proc/sys/net/ipv4/conf/$1/send_redirects
+echo 0 > /proc/sys/net/ipv4/conf/$1/accept_redirects
+
+exit 0
diff --git a/etc/uanytun/p2p-a/config b/etc/uanytun/p2p-a/config
new file mode 100644 (file)
index 0000000..5523ef3
--- /dev/null
@@ -0,0 +1,87 @@
+#############################
+## Main options             #
+#############################
+
+role alice
+
+## device type tun = ip/ipv6, tap = ethernet
+type tun
+
+## Automaticaly configure the interface
+## the address hast to be supplied in CIDR notation
+ifconfig 192.168.223.1/30
+
+## payload encryption algorithm
+#cipher null
+#cipher aes-ctr-128
+#cipher aes-ctr-192
+#cipher aes-ctr-256
+cipher aes-ctr
+
+## message authentication algorithm
+#auth-algo null
+auth-algo sha1
+
+##message auth tag length
+#auth-tag-length 10
+
+## Passphrase
+## this is used to generate the crypto-key and salt
+## this should be al least 30 characters
+passphrase Creating_P2P_VPN_Tunnels_With_Anytun_Is_Easy
+
+## local ip address to bind to (for tunnel data)
+## (if you run an anycast cluster this has to be the anycast ip address)
+#interface <ip-address>
+
+## local port to bind to (for tunnel data)
+## make sure to use a different port for every server and client!
+port 4445
+
+## The remote host and port
+remote-host p2p-b.example.com
+remote-port 4445
+
+#############################
+## Debug options            #
+#############################
+
+## don't run in background
+#nodaemonize
+
+## additional log to standard output with a level of 5
+#log stdout:5
+
+
+#############################
+## Expert options           #
+#############################
+
+## log to syslog with a level of 3
+log syslog:3,uanytun-p2p-a,daemon
+
+## change user and group after init
+username uanytun
+groupname uanytun
+
+## chroot to users home directory
+#chroot /var/run/uanytun
+
+## key derivation pseudo random function
+#kd-prf null
+#kd-prf aes-ctr
+#kd-prf aes-ctr-128
+#kd-prf aes-ctr-192
+#kd-prf aes-ctr-256
+
+## Device name
+#dev uanytun0
+
+## Manually set encryption key and salt
+## (this replaces the passphrase)
+#key 0123456789ABCDEF0123456789ABCDEF
+#salt 0123456789ABCD0123456789ABCD
+
+## Setting a window size > 0 will enable replay protection
+## This most likely will only work with external rekeying
+#window-size 0
diff --git a/etc/uanytun/p2p-b/config b/etc/uanytun/p2p-b/config
new file mode 100644 (file)
index 0000000..5ffe2c9
--- /dev/null
@@ -0,0 +1,87 @@
+#############################
+## Main options             #
+#############################
+
+role bob
+
+## device type tun = ip/ipv6, tap = ethernet
+type tun
+
+## Automaticaly configure the interface
+## the address hast to be supplied in CIDR notation
+ifconfig 192.168.223.2/30
+
+## payload encryption algorithm
+#cipher null
+#cipher aes-ctr-128
+#cipher aes-ctr-192
+#cipher aes-ctr-256
+cipher aes-ctr
+
+## message authentication algorithm
+#auth-algo null
+auth-algo sha1
+
+##message auth tag length
+#auth-tag-length 10
+
+## Passphrase
+## this is used to generate the crypto-key and salt
+## this should be al least 30 characters
+passphrase Creating_P2P_VPN_Tunnels_With_Anytun_Is_Easy
+
+## local ip address to bind to (for tunnel data)
+## (if you run an anycast cluster this has to be the anycast ip address)
+#interface <ip-address>
+
+## local port to bind to (for tunnel data)
+## make sure to use a different port for every server and client!
+port 4445
+
+## The remote host and port
+remote-host p2p-a.example.com
+remote-port 4445
+
+#############################
+## Debug options            #
+#############################
+
+## don't run in background
+#nodaemonize
+
+## additional log to standard output with a level of 5
+#log stdout:5
+
+
+#############################
+## Expert options           #
+#############################
+
+## log to syslog with a level of 3
+log syslog:3,uanytun-p2p-b,daemon
+
+## change user and group after init
+username uanytun
+groupname uanytun
+
+## chroot to users home directory
+#chroot /var/run/uanytun
+
+## key derivation pseudo random function
+#kd-prf null
+#kd-prf aes-ctr
+#kd-prf aes-ctr-128
+#kd-prf aes-ctr-192
+#kd-prf aes-ctr-256
+
+## Device name
+#dev uanytun0
+
+## Manually set encryption key and salt
+## (this replaces the passphrase)
+#key 0123456789ABCDEF0123456789ABCDEF
+#salt 0123456789ABCD0123456789ABCD
+
+## Setting a window size > 0 will enable replay protection
+## This most likely will only work with external rekeying
+#window-size 0
diff --git a/src/Makefile b/src/Makefile
new file mode 100644 (file)
index 0000000..358c612
--- /dev/null
@@ -0,0 +1,148 @@
+##
+##  uAnytun
+##
+##  uAnytun is a tiny implementation of SATP. Unlike Anytun which is a full
+##  featured implementation uAnytun has no support for multiple connections
+##  or synchronisation. It is a small single threaded implementation intended
+##  to act as a client on small platforms.
+##  The secure anycast tunneling protocol (satp) defines a protocol used
+##  for communication between any combination of unicast and anycast
+##  tunnel endpoints.  It has less protocol overhead than IPSec in Tunnel
+##  mode and allows tunneling of every ETHER TYPE protocol (e.g.
+##  ethernet, ip, arp ...). satp directly includes cryptography and
+##  message authentication based on the methodes used by SRTP.  It is
+##  intended to deliver a generic, scaleable and secure solution for
+##  tunneling and relaying of packets of any protocol.
+##  
+##
+##  Copyright (C) 2007-2008 Christian Pointner <equinox@anytun.org>
+##
+##  This file is part of uAnytun.
+##
+##  uAnytun is free software: you can redistribute it and/or modify
+##  it under the terms of the GNU General Public License version 3 as
+##  published by the Free Software Foundation.
+##
+##  uAnytun 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 uAnytun. If not, see <http://www.gnu.org/licenses/>.
+##
+
+ifneq ($(MAKECMDGOALS),distclean)
+include include.mk
+endif
+
+EXECUTABLE := uanytun
+
+CRYPT_OBJ := key_derivation.o \
+            auth_algo.o
+OBJ := log.o \
+      string_list.o \
+      sig_handler.o \
+      options.o \
+      tun.o \
+      udp.o \
+      plain_packet.o \
+      encrypted_packet.o \
+      seq_window.o \
+      cipher.o \
+      uanytun.o
+
+
+ifndef NO_CRYPT_OBJ
+OBJ += $(CRYPT_OBJ)
+endif
+
+SRC := $(OBJ:%.o=%.c)
+
+.PHONY: clean distclean manpage install install-bin install-etc install-man remove purge
+
+all: $(EXECUTABLE)
+
+%.d: %.c
+       @set -e; rm -f $@; \
+        $(CC) -MM $(CFLAGS) $< > $@.$$$$; \
+   sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
+   rm -f $@.$$$$; echo '(re)building $@'
+
+ifneq ($(MAKECMDGOALS),distclean)
+-include $(SRC:%.c=%.d)
+endif
+
+uanytun: $(OBJ)
+       $(CC) $(OBJ) -o $@ $(LDFLAGS)
+
+%.o: %.c
+       $(CC) $(CFLAGS) -c $<
+
+
+distclean: clean
+       find . -name *.o -exec rm -f {} \;
+       find . -name "*.\~*" -exec rm -rf {} \;
+       rm -f include.mk
+       rm -f tun.c
+
+clean:
+       rm -f *.o
+       rm -f *.d
+       rm -f *.d.*
+       rm -f $(EXECUTABLE)
+
+manpage:
+       $(MAKE) --directory="../doc/" manpage
+
+install: all install-bin install-etc install-man add-user
+
+install-bin: $(EXECUTABLE)
+       mkdir -p $(DESTDIR)$(SBINDIR)
+       install -m 755 $(EXECUTABLE) $(DESTDIR)$(SBINDIR)
+       $(STRIP) $(DESTDIR)$(SBINDIR)/$(EXECUTABLE)
+
+install-etc:
+       mkdir -p $(DESTDIR)$(ETCDIR)/uanytun
+       install -m 644 ../etc/uanytun/autostart $(DESTDIR)$(ETCDIR)/uanytun/autostart
+       @( cd '../etc/uanytun/' ;                                                                                \
+     for dir in `ls`; do                                                                                   \
+       if [ -d $$dir ]; then                                                                               \
+         echo "install $$dir configuration" ;                                                              \
+         cd $$dir ;                                                                                        \
+         mkdir -p $(DESTDIR)$(ETCDIR)/uanytun/$$dir ;                                                      \
+         install -m 600 config $(DESTDIR)$(ETCDIR)/uanytun/$$dir/config ;                                  \
+         sed -i 's#username uanytun#username $(USERNAME)#' $(DESTDIR)$(ETCDIR)/uanytun/$$dir/config ;      \
+         sed -i 's#groupname uanytun#groupname $(USERNAME)#' $(DESTDIR)$(ETCDIR)/uanytun/$$dir/config ;    \
+         sed -i 's#chroot /var/run/uanytun#chroot $(USERHOME)#' $(DESTDIR)$(ETCDIR)/uanytun/$$dir/config ; \
+         if [ -e 'post-up.sh' ]; then                                                                      \
+           install -m 755 post-up.sh $(DESTDIR)$(ETCDIR)/uanytun/$$dir/post-up.sh ;                        \
+         fi ;                                                                                              \
+         cd .. ;                                                                                           \
+       fi ;                                                                                                \
+     done                                                                                                  \
+   )
+       mkdir -p $(DESTDIR)$(ETCDIR)/init.d
+       install -m 755 ../etc/init.d/uanytun $(DESTDIR)$(ETCDIR)/init.d/$(EXECUTABLE)
+       @ sed -i 's#DAEMON=/usr/sbin/uanytun#DAEMON=$(SBINDIR)/$(EXECUTABLE)#' $(DESTDIR)$(ETCDIR)/init.d/$(EXECUTABLE)
+       @ sed -i 's#CONFIG_DIR=/etc/uanytun#CONFIG_DIR=$(ETCDIR)/uanytun#' $(DESTDIR)$(ETCDIR)/init.d/$(EXECUTABLE)
+
+install-man: manpage
+       mkdir -p $(DESTDIR)$(MANDIR)/man8/
+       cp ../doc/uanytun.8 $(DESTDIR)$(MANDIR)/man8/$(EXECUTABLE).8
+       gzip $(DESTDIR)$(MANDIR)/man8/$(EXECUTABLE).8
+
+add-user:
+       @ adduser --system --group --home $(USERHOME) $(USERNAME)
+
+remove-user: 
+       @ deluser $(USERNAME)
+       @ rm -rf $(USERHOME)
+
+remove:
+       rm -f $(DESTDIR)$(SBINDIR)/$(EXECUTABLE)
+       rm -f $(DESTDIR)$(MANDIR)/man8/$(EXECUTABLE).8.gz
+       rm -f $(DESTDIR)$(ETCDIR)/init.d/$(EXECUTABLE)
+
+purge: remove remove-user
+       rm -rf $(DESTDIR)$(ETCDIR)/uanytun/
diff --git a/src/auth_algo.c b/src/auth_algo.c
new file mode 100644 (file)
index 0000000..d015cc5
--- /dev/null
@@ -0,0 +1,291 @@
+/*
+ *  uAnytun
+ *
+ *  uAnytun is a tiny implementation of SATP. Unlike Anytun which is a full
+ *  featured implementation uAnytun has no support for multiple connections
+ *  or synchronisation. It is a small single threaded implementation intended
+ *  to act as a client on small platforms.
+ *  The secure anycast tunneling protocol (satp) defines a protocol used
+ *  for communication between any combination of unicast and anycast
+ *  tunnel endpoints.  It has less protocol overhead than IPSec in Tunnel
+ *  mode and allows tunneling of every ETHER TYPE protocol (e.g.
+ *  ethernet, ip, arp ...). satp directly includes cryptography and
+ *  message authentication based on the methodes used by SRTP.  It is
+ *  intended to deliver a generic, scaleable and secure solution for
+ *  tunneling and relaying of packets of any protocol.
+ *  
+ *
+ *  Copyright (C) 2007-2008 Christian Pointner <equinox@anytun.org>
+ *
+ *  This file is part of uAnytun.
+ *
+ *  uAnytun is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 3 as
+ *  published by the Free Software Foundation.
+ *
+ *  uAnytun 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 uAnytun. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "datatypes.h"
+
+#include "encrypted_packet.h"
+
+#include "auth_algo.h"
+
+#include "log.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+auth_algo_type_t auth_algo_get_type(const char* type)
+{
+  if(!strcmp(type, "null"))
+    return aa_null;
+  else if(!strcmp(type, "sha1"))
+    return aa_sha1;
+  
+  return aa_unknown;
+}
+
+u_int32_t auth_algo_get_max_length(const char* type)
+{
+  switch(auth_algo_get_type(type)) {
+  case aa_null: return 0;
+  case aa_sha1: return SHA1_LENGTH;
+  default: return 0;
+  }
+}
+
+int auth_algo_init(auth_algo_t* aa, const char* type)
+{
+  if(!aa) 
+    return -1;
+
+  aa->type_ = auth_algo_get_type(type);
+  if(aa->type_ == aa_unknown) {
+    log_printf(ERROR, "unknown auth algo type");
+    return -1;
+  }
+
+  aa->params_ = NULL;
+
+  aa->key_.buf_ = NULL;
+  aa->key_.length_ = 0;
+
+  int ret = 0;
+  if(aa->type_ == aa_sha1)
+    ret = auth_algo_sha1_init(aa);
+
+  if(ret)
+    auth_algo_close(aa);
+
+  return ret;
+}
+
+void auth_algo_close(auth_algo_t* aa)
+{
+  if(!aa)
+    return;
+
+  if(aa->type_ == aa_sha1)
+    auth_algo_sha1_close(aa);
+
+  if(aa->key_.buf_)
+    free(aa->key_.buf_);
+}
+
+void auth_algo_generate(auth_algo_t* aa, key_derivation_t* kd, key_derivation_dir_t dir, encrypted_packet_t* packet)
+{
+  if(!aa) 
+    return;
+
+  if(aa->type_ == aa_null)
+    return;
+  else if(aa->type_ == aa_sha1)
+    auth_algo_sha1_generate(aa, kd, dir, packet);
+  else {
+    log_printf(ERROR, "unknown auth algo type");
+    return;
+  }
+}
+
+int auth_algo_check_tag(auth_algo_t* aa, key_derivation_t* kd, key_derivation_dir_t dir, encrypted_packet_t* packet)
+{
+  if(!aa) 
+    return 0;
+
+  if(aa->type_ == aa_null)
+    return 1;
+  else if(aa->type_ == aa_sha1)
+    return auth_algo_sha1_check_tag(aa, kd, dir, packet);
+  else {
+    log_printf(ERROR, "unknown auth algo type");
+    return 0;
+  }
+}
+
+/* ---------------- HMAC Sha1 Auth Algo ---------------- */
+
+int auth_algo_sha1_init(auth_algo_t* aa)
+{
+  if(!aa)
+    return -1;
+
+  if(aa->key_.buf_)
+    free(aa->key_.buf_);
+
+  aa->key_.length_ = SHA1_LENGTH;
+  aa->key_.buf_ = malloc(aa->key_.length_);
+  if(!aa->key_.buf_)
+    return -2;
+
+  if(aa->params_)
+    free(aa->params_);
+  aa->params_ = malloc(sizeof(auth_algo_sha1_param_t));
+  if(!aa->params_)
+    return -2;
+
+  auth_algo_sha1_param_t* params = aa->params_;
+
+#ifndef USE_SSL_CRYPTO
+  gcry_error_t err = gcry_md_open(&params->handle_, GCRY_MD_SHA1, GCRY_MD_FLAG_HMAC);
+  if(err) {
+    log_printf(ERROR, "failed to open message digest algo: %s", gcry_strerror(err));
+    return -1;
+  } 
+#else
+  HMAC_CTX_init(&params->ctx_);
+  HMAC_Init_ex(&params->ctx_, NULL, 0, EVP_sha1(), NULL);
+#endif
+
+  return 0;
+}
+
+void auth_algo_sha1_close(auth_algo_t* aa)
+{
+  if(!aa)
+    return;
+
+  if(aa->params_) {
+    auth_algo_sha1_param_t* params = aa->params_;
+
+#ifndef USE_SSL_CRYPTO
+    if(params->handle_)
+      gcry_md_close(params->handle_);
+#else
+    HMAC_CTX_cleanup(&params->ctx_);
+#endif    
+
+    free(aa->params_);
+  }
+
+}
+
+void auth_algo_sha1_generate(auth_algo_t* aa, key_derivation_t* kd, key_derivation_dir_t dir, encrypted_packet_t* packet)
+{
+  if(!encrypted_packet_get_auth_tag_length(packet))
+    return;
+
+  if(!aa || !aa->params_) {
+    log_printf(ERROR, "auth algo not initialized");
+    return;
+  }
+  if(!kd) {
+    log_printf(ERROR, "no key derivation supplied");
+    return;
+  }
+  auth_algo_sha1_param_t* params = aa->params_;
+
+  int ret = key_derivation_generate(kd, dir, LABEL_AUTH, encrypted_packet_get_seq_nr(packet), aa->key_.buf_, aa->key_.length_);
+  if(ret < 0)
+    return;
+
+#ifndef USE_SSL_CRYPTO
+  gcry_error_t err = gcry_md_setkey(params->handle_, aa->key_.buf_, aa->key_.length_);
+  if(err) {
+    log_printf(ERROR, "failed to set hmac key: %s", gcry_strerror(err));
+    return;
+  } 
+  
+  gcry_md_reset(params->handle_);
+  gcry_md_write(params->handle_, encrypted_packet_get_auth_portion(packet), encrypted_packet_get_auth_portion_length(packet));
+  gcry_md_final(params->handle_);
+  u_int8_t* hmac = gcry_md_read(params->handle_, 0);
+#else
+  HMAC_Init_ex(&params->ctx_, aa->key_.buf_, aa->key_.length_, EVP_sha1(), NULL);
+
+  u_int8_t hmac[SHA1_LENGTH];
+  HMAC_Update(&params->ctx_, encrypted_packet_get_auth_portion(packet), encrypted_packet_get_auth_portion_length(packet));
+  HMAC_Final(&params->ctx_, hmac, NULL);
+#endif
+
+  u_int8_t* tag = encrypted_packet_get_auth_tag(packet);
+  u_int32_t length = (encrypted_packet_get_auth_tag_length(packet) < SHA1_LENGTH) ? encrypted_packet_get_auth_tag_length(packet) : SHA1_LENGTH;
+
+  if(length > SHA1_LENGTH)
+    memset(tag, 0, encrypted_packet_get_auth_tag_length(packet));
+
+  memcpy(&tag[encrypted_packet_get_auth_tag_length(packet) - length], &hmac[SHA1_LENGTH - length], length);
+}
+
+
+int auth_algo_sha1_check_tag(auth_algo_t* aa, key_derivation_t* kd, key_derivation_dir_t dir, encrypted_packet_t* packet)
+{
+  if(!encrypted_packet_get_auth_tag_length(packet))
+    return 1;
+
+  if(!aa || !aa->params_) {
+    log_printf(ERROR, "auth algo not initialized");
+    return 0;
+  }
+  if(!kd) {
+    log_printf(ERROR, "no key derivation supplied");
+    return 0;
+  }
+  auth_algo_sha1_param_t* params = aa->params_;
+
+  int ret = key_derivation_generate(kd, dir, LABEL_AUTH, encrypted_packet_get_seq_nr(packet), aa->key_.buf_, aa->key_.length_);
+  if(ret < 0)
+    return 0;
+
+#ifndef USE_SSL_CRYPTO
+  gcry_error_t err = gcry_md_setkey(params->handle_, aa->key_.buf_, aa->key_.length_);
+  if(err) {
+    log_printf(ERROR, "failed to set hmac key: %s", gcry_strerror(err));
+    return -1;
+  } 
+
+  gcry_md_reset(params->handle_);
+  gcry_md_write(params->handle_, encrypted_packet_get_auth_portion(packet), encrypted_packet_get_auth_portion_length(packet));
+  gcry_md_final(params->handle_);
+  u_int8_t* hmac = gcry_md_read(params->handle_, 0);
+#else
+  HMAC_Init_ex(&params->ctx_, aa->key_.buf_, aa->key_.length_, EVP_sha1(), NULL);
+
+  u_int8_t hmac[SHA1_LENGTH];
+  HMAC_Update(&params->ctx_, encrypted_packet_get_auth_portion(packet), encrypted_packet_get_auth_portion_length(packet));
+  HMAC_Final(&params->ctx_, hmac, NULL);
+#endif
+
+  u_int8_t* tag = encrypted_packet_get_auth_tag(packet);
+  u_int32_t length = (encrypted_packet_get_auth_tag_length(packet) < SHA1_LENGTH) ? encrypted_packet_get_auth_tag_length(packet) : SHA1_LENGTH;
+
+  if(length > SHA1_LENGTH) {
+    u_int32_t i;
+    for(i=0; i < (encrypted_packet_get_auth_tag_length(packet) - SHA1_LENGTH); ++i)
+      if(tag[i]) return 0; 
+  }
+  
+  int result = memcmp(&tag[encrypted_packet_get_auth_tag_length(packet) - length], &hmac[SHA1_LENGTH - length], length);
+  
+  if(result)
+    return 0;
+
+  return 1;
+}
diff --git a/src/auth_algo.h b/src/auth_algo.h
new file mode 100644 (file)
index 0000000..baf32c5
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ *  uAnytun
+ *
+ *  uAnytun is a tiny implementation of SATP. Unlike Anytun which is a full
+ *  featured implementation uAnytun has no support for multiple connections
+ *  or synchronisation. It is a small single threaded implementation intended
+ *  to act as a client on small platforms.
+ *  The secure anycast tunneling protocol (satp) defines a protocol used
+ *  for communication between any combination of unicast and anycast
+ *  tunnel endpoints.  It has less protocol overhead than IPSec in Tunnel
+ *  mode and allows tunneling of every ETHER TYPE protocol (e.g.
+ *  ethernet, ip, arp ...). satp directly includes cryptography and
+ *  message authentication based on the methodes used by SRTP.  It is
+ *  intended to deliver a generic, scaleable and secure solution for
+ *  tunneling and relaying of packets of any protocol.
+ *  
+ *
+ *  Copyright (C) 2007-2008 Christian Pointner <equinox@anytun.org>
+ *
+ *  This file is part of uAnytun.
+ *
+ *  uAnytun is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 3 as
+ *  published by the Free Software Foundation.
+ *
+ *  uAnytun 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 uAnytun. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _AUTH_ALGO_H_
+#define _AUTH_ALGO_H_
+
+#ifndef USE_SSL_CRYPTO
+#include <gcrypt.h>
+#else
+#include <openssl/hmac.h>
+#endif
+#include "key_derivation.h"
+#include "encrypted_packet.h"
+
+enum auth_algo_type_enum { aa_unknown, aa_null, aa_sha1 };
+typedef enum auth_algo_type_enum auth_algo_type_t;
+
+struct auth_algo_struct {
+  auth_algo_type_t type_;
+  buffer_t key_;
+  void* params_;
+};
+typedef struct auth_algo_struct auth_algo_t;
+
+auth_algo_type_t auth_algo_get_type(const char* type);
+u_int32_t auth_algo_get_max_length(const char* type);
+int auth_algo_init(auth_algo_t* aa, const char* type);
+void auth_algo_close(auth_algo_t* aa);
+
+void auth_algo_generate(auth_algo_t* aa, key_derivation_t* kd, key_derivation_dir_t dir, encrypted_packet_t* packet);
+int auth_algo_check_tag(auth_algo_t* aa, key_derivation_t* kd, key_derivation_dir_t dir, encrypted_packet_t* packet);
+
+
+#define SHA1_LENGTH 20
+
+struct auth_algo_sha1_param_struct {
+#ifndef USE_SSL_CRYPTO
+  gcry_md_hd_t handle_;
+#else
+  HMAC_CTX ctx_;
+#endif
+};
+typedef struct auth_algo_sha1_param_struct auth_algo_sha1_param_t;
+
+int auth_algo_sha1_init(auth_algo_t* aa);
+void auth_algo_sha1_close(auth_algo_t* aa);
+void auth_algo_sha1_generate(auth_algo_t* aa, key_derivation_t* kd, key_derivation_dir_t dir, encrypted_packet_t* packet);
+int auth_algo_sha1_check_tag(auth_algo_t* aa, key_derivation_t* kd, key_derivation_dir_t dir, encrypted_packet_t* packet);
+
+#endif
diff --git a/src/bsd/tun.c b/src/bsd/tun.c
new file mode 100644 (file)
index 0000000..f193668
--- /dev/null
@@ -0,0 +1,348 @@
+/*
+ *  uAnytun
+ *
+ *  uAnytun is a tiny implementation of SATP. Unlike Anytun which is a full
+ *  featured implementation uAnytun has no support for multiple connections
+ *  or synchronisation. It is a small single threaded implementation intended
+ *  to act as a client on small platforms.
+ *  The secure anycast tunneling protocol (satp) defines a protocol used
+ *  for communication between any combination of unicast and anycast
+ *  tunnel endpoints.  It has less protocol overhead than IPSec in Tunnel
+ *  mode and allows tunneling of every ETHER TYPE protocol (e.g.
+ *  ethernet, ip, arp ...). satp directly includes cryptography and
+ *  message authentication based on the methodes used by SRTP.  It is
+ *  intended to deliver a generic, scaleable and secure solution for
+ *  tunneling and relaying of packets of any protocol.
+ *  
+ *
+ *  Copyright (C) 2007-2008 Christian Pointner <equinox@anytun.org>
+ *
+ *  This file is part of uAnytun.
+ *
+ *  uAnytun is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 3 as
+ *  published by the Free Software Foundation.
+ *
+ *  uAnytun 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 uAnytun. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "datatypes.h"
+
+#include "tun.h"
+
+#include "tun_helper.h"
+
+#include "log.h"
+
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/wait.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <net/if_tun.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/uio.h>
+#include <netinet/in_systm.h>
+#include <netinet/in.h>
+#include <netinet/ip.h>
+#define DEVICE_FILE_MAX 255
+
+int tun_init(tun_device_t* dev, const char* dev_name, const char* dev_type, const char* ifcfg_addr, u_int16_t ifcfg_prefix)
+{
+  if(!dev) 
+    return -1;
+  tun_conf(dev, dev_name, dev_type, ifcfg_addr, ifcfg_prefix, 1400);
+  dev->actual_name_ = NULL;
+
+  char* device_file = NULL;
+  char* actual_name_start = NULL;
+  int dynamic = 1;
+  if(dev_name) {
+    asprintf(&device_file, "/dev/%s", dev_name);
+    dynamic = 0;
+  }
+#if defined(__GNUC__) && defined(__OpenBSD__)
+  else if(dev->type_ == TYPE_TUN || dev->type_ == TYPE_TAP) {
+    asprintf(&device_file, "/dev/tun");
+    actual_name_start = "tun";
+  }
+#else
+  else if(dev->type_ == TYPE_TUN) {
+    asprintf(&device_file, "/dev/tun");
+    actual_name_start = "tun";
+  }
+  else if(dev->type_ == TYPE_TAP) {
+    asprintf(&device_file, "/dev/tap");
+    actual_name_start = "tap";
+  }
+#endif
+  else {
+    log_printf(ERROR, "unable to recognize type of device (tun or tap)");
+    tun_close(dev);
+    return -1;
+  }
+  if(!device_file) {
+    log_printf(ERROR, "can't open device file: memory error");
+    tun_close(dev);
+    return -2;
+  }
+
+  u_int32_t dev_id=0;
+  if(dynamic) {
+    for(; dev_id <= DEVICE_FILE_MAX; ++dev_id) {
+      char* device_file_tmp = NULL;
+      asprintf(&device_file_tmp, "%s%d", device_file, dev_id);
+
+      if(!device_file_tmp) {
+        log_printf(ERROR, "can't open device file: memory error");
+        free(device_file);
+        tun_close(dev);
+        return -2;
+      }
+        
+      dev->fd_ = open(device_file_tmp, O_RDWR);
+      free(device_file_tmp);
+      if(dev->fd_ >= 0)
+        break;
+    }
+  }
+  else
+    dev->fd_ = open(device_file, O_RDWR);
+  free(device_file);
+
+  if(dev->fd_ < 0) {
+    if(dynamic)
+      log_printf(ERROR, "can't open device file dynamically: no unused node left");
+    else
+      log_printf(ERROR, "can't open device file (%s): %s", device_file, strerror(errno));
+    
+    tun_close(dev);
+    return -1;
+  }
+
+  if(dynamic)
+    asprintf(&(dev->actual_name_), "%s%d", actual_name_start, dev_id);
+  else
+    dev->actual_name_ = strdup(dev_name);
+
+  if(!dev->actual_name_) {
+    log_printf(ERROR, "can't open device file: memory error");
+    tun_close(dev);
+    return -2;
+  }
+
+  int ret = tun_init_post(dev);
+  if(ret) {
+    tun_close(dev);
+    return ret;
+  }
+
+  if(ifcfg_addr)
+    tun_do_ifconfig(dev);
+
+  return 0;
+}
+
+
+#if defined(__GNUC__) && defined(__OpenBSD__)
+
+int tun_init_post(tun_device_t* dev)
+{
+  if(!dev)
+    return -1;
+
+  dev->with_pi_ = 1;
+  if(dev->type_ == TYPE_TAP)
+    dev->with_pi_ = 0;
+  
+  struct tuninfo ti;  
+
+  if(ioctl(dev->fd_, TUNGIFINFO, &ti) < 0) {
+    log_printf(ERROR, "can't enable multicast for interface: %s", strerror(errno));
+    return -1;
+  }  
+
+  ti.flags |= IFF_MULTICAST;
+  if(dev->type_ == TYPE_TUN)
+    ti.flags &= ~IFF_POINTOPOINT;
+  
+  if(ioctl(dev->fd_, TUNSIFINFO, &ti) < 0) {
+    log_printf(ERROR, "can't enable multicast for interface: %s", strerror(errno));
+    return -1;
+  }
+  return 0;
+}
+
+#elif defined(__GNUC__) && defined(__FreeBSD__)
+
+int tun_init_post(tun_device_t* dev)
+{
+  if(!dev)
+    return -1;
+
+  dev->with_pi_ = 1;
+  if(dev->type_ == TYPE_TAP)
+    dev->with_pi_ = 0;
+
+  if(dev->type_ == TYPE_TUN) {
+    int arg = 0;
+    if(ioctl(dev->fd_, TUNSLMODE, &arg) < 0) {
+      log_printf(ERROR, "can't disable link-layer mode for interface: %s", strerror(errno));
+      return -1;
+    }  
+
+    arg = 1;
+    if(ioctl(dev->fd_, TUNSIFHEAD, &arg) < 0) {
+      log_printf(ERROR, "can't enable multi-af mode for interface: %s", strerror(errno));
+      return -1;
+    }  
+
+    arg = IFF_BROADCAST;
+    arg |= IFF_MULTICAST;
+    if(ioctl(dev->fd_, TUNSIFMODE, &arg) < 0) {
+      log_printf(ERROR, "can't enable multicast for interface: %s", strerror(errno));
+      return -1;
+    }  
+  }
+
+  return 0;
+}
+
+#elif defined(__GNUC__) && defined(__NetBSD__)
+ #warning this device has never been tested on NetBSD and might not work
+int tun_init_post(tun_device_t* dev)
+{
+  if(!dev)
+    return -1;
+
+  dev->with_pi_ = 0;
+
+  int arg = IFF_POINTOPOINT|IFF_MULTICAST;
+  ioctl(dev->fd_, TUNSIFMODE, &arg);
+  arg = 0;
+  ioctl(dev->fd_, TUNSLMODE, &arg);
+
+  return 0;
+}
+
+#else
+ #error This Device works just for OpenBSD, FreeBSD or NetBSD
+#endif
+
+
+
+void tun_close(tun_device_t* dev)
+{
+  if(!dev)
+    return;
+
+  if(dev->fd_ > 0)
+    close(dev->fd_);
+
+  if(dev->actual_name_)
+    free(dev->actual_name_);
+
+  if(dev->net_addr_)
+    free(dev->net_addr_);
+
+  if(dev->net_mask_)
+    free(dev->net_mask_);
+}
+
+int tun_read(tun_device_t* dev, u_int8_t* buf, u_int32_t len)
+{
+  if(!dev || dev->fd_ < 0)
+    return -1;
+
+  if(dev->with_pi_)
+  {
+    struct iovec iov[2];
+    u_int32_t type;
+    
+    iov[0].iov_base = &type;
+    iov[0].iov_len = sizeof(type);
+    iov[1].iov_base = buf;
+    iov[1].iov_len = len;
+    return(tun_fix_return(readv(dev->fd_, iov, 2), sizeof(type)));
+  }
+  else
+    return(read(dev->fd_, buf, len));
+}
+
+int tun_write(tun_device_t* dev, u_int8_t* buf, u_int32_t len)
+{
+  if(!dev || dev->fd_ < 0)
+    return -1;
+
+  if(!buf)
+    return 0;
+
+  if(dev->with_pi_)
+  {
+    struct iovec iov[2];
+    u_int32_t type;
+    struct ip *hdr = (struct ip*)buf;
+    
+    type = 0;
+    if(hdr->ip_v == 4)
+      type = htonl(AF_INET);
+    else
+      type = htonl(AF_INET6);
+    
+    iov[0].iov_base = &type;
+    iov[0].iov_len = sizeof(type);
+    iov[1].iov_base = buf;
+    iov[1].iov_len = len;
+    return(tun_fix_return(writev(dev->fd_, iov, 2), sizeof(type)));
+  }
+  else
+    return(write(dev->fd_, buf, len));
+}
+
+void tun_do_ifconfig(tun_device_t* dev)
+{
+  if(!dev || !dev->actual_name_ || !dev->net_addr_ || !dev->net_mask_)
+    return;
+
+
+  char* command = NULL;
+  char* netmask;
+  char* end;
+  if(dev->type_ == TYPE_TAP) {
+#if defined(__GNUC__) && defined(__OpenBSD__)
+    end = " link0";
+#elif defined(__GNUC__) && defined(__FreeBSD__)
+    end = " up";
+#elif defined(__GNUC__) && defined(__NetBSD__)
+    end = "";
+#else
+ #error This Device works just for OpenBSD, FreeBSD or NetBSD
+#endif
+  }
+  else
+    end = " up";
+
+  asprintf(&command, "/sbin/ifconfig %s %s netmask %s mtu %d%s", dev->actual_name_, dev->net_addr_,
+                                                                 dev->net_mask_, dev->mtu_, end);
+  if(!command) {
+    log_printf(ERROR, "Execution of ifconfig failed");
+    return;
+  }
+
+  int result = system(command);
+  if(result == -1)
+    log_printf(ERROR, "Execution of ifconfig failed");
+  else
+    log_printf(NOTICE, "ifconfig returned %d", WEXITSTATUS(result));
+
+  free(command);
+}
diff --git a/src/cipher.c b/src/cipher.c
new file mode 100644 (file)
index 0000000..5fba4af
--- /dev/null
@@ -0,0 +1,335 @@
+/*
+ *  uAnytun
+ *
+ *  uAnytun is a tiny implementation of SATP. Unlike Anytun which is a full
+ *  featured implementation uAnytun has no support for multiple connections
+ *  or synchronisation. It is a small single threaded implementation intended
+ *  to act as a client on small platforms.
+ *  The secure anycast tunneling protocol (satp) defines a protocol used
+ *  for communication between any combination of unicast and anycast
+ *  tunnel endpoints.  It has less protocol overhead than IPSec in Tunnel
+ *  mode and allows tunneling of every ETHER TYPE protocol (e.g.
+ *  ethernet, ip, arp ...). satp directly includes cryptography and
+ *  message authentication based on the methodes used by SRTP.  It is
+ *  intended to deliver a generic, scaleable and secure solution for
+ *  tunneling and relaying of packets of any protocol.
+ *  
+ *
+ *  Copyright (C) 2007-2008 Christian Pointner <equinox@anytun.org>
+ *
+ *  This file is part of uAnytun.
+ *
+ *  uAnytun is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 3 as
+ *  published by the Free Software Foundation.
+ *
+ *  uAnytun 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 uAnytun. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "datatypes.h"
+
+#include "plain_packet.h"
+#include "encrypted_packet.h"
+
+#include "cipher.h"
+
+#include "log.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+int cipher_init(cipher_t* c, const char* type)
+{
+  if(!c) 
+    return -1;
+
+  c->key_length_ = 0;
+
+  c->type_ = c_unknown;
+  if(!strcmp(type, "null"))
+    c->type_ = c_null;
+#ifndef NO_CRYPT
+  else if(!strncmp(type, "aes-ctr", 7)) {
+    c->type_ = c_aes_ctr;
+    if(type[7] == 0) {
+      c->key_length_ = C_AESCTR_DEFAULT_KEY_LENGTH;
+    }
+    else if(type[7] != '-') 
+      return -1;
+    else {
+      const char* tmp = &type[8];
+      c->key_length_ = atoi(tmp);
+    }
+  }
+#endif
+  else {
+    log_printf(ERROR, "unknown cipher type");
+    return -1;
+  }
+
+  c->params_ = NULL;
+
+  c->key_.buf_ = NULL;
+  c->key_.length_ = 0;
+
+  c->salt_.buf_ = NULL;
+  c->salt_.length_ = 0;
+
+  int ret = 0;
+#ifndef NO_CRYPT
+  if(c->type_ == c_aes_ctr)
+    ret = cipher_aesctr_init(c);
+#endif
+
+  if(ret)
+    cipher_close(c);
+
+  return ret;
+}
+
+void cipher_close(cipher_t* c)
+{
+  if(!c)
+    return;
+
+#ifndef NO_CRYPT
+  if(c->type_ == c_aes_ctr)
+    cipher_aesctr_close(c);
+#endif
+
+  if(c->key_.buf_)
+    free(c->key_.buf_);
+  if(c->salt_.buf_)
+    free(c->salt_.buf_);
+}
+
+
+int cipher_encrypt(cipher_t* c, key_derivation_t* kd, key_derivation_dir_t dir, plain_packet_t* in, encrypted_packet_t* out, seq_nr_t seq_nr, sender_id_t sender_id, mux_t mux)
+{
+  if(!c) 
+    return -1;
+
+       int32_t len;
+  if(c->type_ == c_null)
+    len = cipher_null_crypt(plain_packet_get_packet(in), plain_packet_get_length(in), 
+                            encrypted_packet_get_payload(out), encrypted_packet_get_payload_length(out));
+#ifndef NO_CRYPT
+  else if(c->type_ == c_aes_ctr)
+    len = cipher_aesctr_crypt(c, kd, dir, plain_packet_get_packet(in), plain_packet_get_length(in),
+                              encrypted_packet_get_payload(out), encrypted_packet_get_payload_length(out),
+                              seq_nr, sender_id, mux);
+#endif
+  else {
+    log_printf(ERROR, "unknown cipher type");
+    return -1;
+  }
+
+  if(len < 0)
+    return 0;
+
+       encrypted_packet_set_sender_id(out, sender_id);
+  encrypted_packet_set_seq_nr(out, seq_nr);
+  encrypted_packet_set_mux(out, mux);
+
+  encrypted_packet_set_payload_length(out, len);
+
+  return 0;
+}
+
+int cipher_decrypt(cipher_t* c, key_derivation_t* kd, key_derivation_dir_t dir, encrypted_packet_t* in, plain_packet_t* out)
+{
+  if(!c) 
+    return -1;
+
+       int32_t len;
+  if(c->type_ == c_null)
+    len = cipher_null_crypt(encrypted_packet_get_payload(in), encrypted_packet_get_payload_length(in),
+                            plain_packet_get_packet(out), plain_packet_get_length(out));
+#ifndef NO_CRYPT
+  else if(c->type_ == c_aes_ctr)
+    len = cipher_aesctr_crypt(c, kd, dir, encrypted_packet_get_payload(in), encrypted_packet_get_payload_length(in),
+                              plain_packet_get_packet(out), plain_packet_get_length(out),
+                              encrypted_packet_get_seq_nr(in), encrypted_packet_get_sender_id(in),
+                              encrypted_packet_get_mux(in));
+#endif
+  else {
+    log_printf(ERROR, "unknown cipher type");
+    return -1;
+  }
+  
+  if(len < 0)
+    return 0;
+
+       plain_packet_set_length(out, len);
+
+  return 0;
+}
+
+/* ---------------- NULL Cipher ---------------- */
+
+int32_t cipher_null_crypt(u_int8_t* in, u_int32_t ilen, u_int8_t* out, u_int32_t olen)
+{
+       memcpy(out, in, (ilen < olen) ? ilen : olen);
+  return (ilen < olen) ? ilen : olen;
+}
+
+#ifndef NO_CRYPT
+/* ---------------- AES-Ctr Cipher ---------------- */
+
+int cipher_aesctr_init(cipher_t* c)
+{
+  if(!c)
+    return -1;
+
+  if(c->key_.buf_)
+    free(c->key_.buf_);
+
+  c->key_.length_ = c->key_length_/8;
+  c->key_.buf_ = malloc(c->key_.length_);
+  if(!c->key_.buf_)
+    return -2;
+
+  if(c->salt_.buf_)
+    free(c->salt_.buf_);
+
+  c->salt_.length_ = C_AESCTR_SALT_LENGTH;
+  c->salt_.buf_ = malloc(c->salt_.length_);
+  if(!c->salt_.buf_)
+    return -2;
+
+  if(c->params_)
+    free(c->params_);
+  c->params_ = malloc(sizeof(cipher_aesctr_param_t));
+  if(!c->params_)
+    return -2;
+
+  cipher_aesctr_param_t* params = c->params_;
+
+#ifndef USE_SSL_CRYPTO
+  int algo;
+  switch(c->key_length_) {
+  case 128: algo = GCRY_CIPHER_AES128; break;
+  case 192: algo = GCRY_CIPHER_AES192; break;
+  case 256: algo = GCRY_CIPHER_AES256; break;
+  default: {
+    log_printf(ERROR, "cipher key length of %d Bits is not supported", c->key_length_);
+    return -1;
+  }
+  }
+
+  gcry_error_t err = gcry_cipher_open(&params->handle_, algo, GCRY_CIPHER_MODE_CTR, 0);
+  if(err) {
+    log_printf(ERROR, "failed to open cipher: %s", gcry_strerror(err));
+    return -1;
+  } 
+#endif
+
+  return 0;
+}
+
+void cipher_aesctr_close(cipher_t* c)
+{
+  if(!c)
+    return;
+
+  if(c->params_) {
+    cipher_aesctr_param_t* params = c->params_;
+
+#ifndef USE_SSL_CRYPTO
+    if(params->handle_)
+      gcry_cipher_close(params->handle_);
+#endif
+
+    free(c->params_);
+  }
+}
+
+int cipher_aesctr_calc_ctr(cipher_t* c, key_derivation_t* kd, key_derivation_dir_t dir, seq_nr_t seq_nr, sender_id_t sender_id, mux_t mux)
+{
+  if(!c || !c->params_)
+    return -1;
+  
+  cipher_aesctr_param_t* params = c->params_;
+
+  int ret = key_derivation_generate(kd, dir, LABEL_SALT, seq_nr, c->salt_.buf_, C_AESCTR_SALT_LENGTH);
+  if(ret < 0)
+    return ret;
+
+  memcpy(params->ctr_.salt_.buf_, c->salt_.buf_, C_AESCTR_SALT_LENGTH);
+  params->ctr_.salt_.zero_ = 0;
+  params->ctr_.params_.mux_ ^= MUX_T_HTON(mux);
+  params->ctr_.params_.sender_id_ ^= SENDER_ID_T_HTON(sender_id);
+  params->ctr_.params_.seq_nr_ ^= SEQ_NR_T_HTON(seq_nr);
+
+  return 0;
+}
+
+int32_t cipher_aesctr_crypt(cipher_t* c, key_derivation_t* kd, key_derivation_dir_t dir, u_int8_t* in, u_int32_t ilen, u_int8_t* out, u_int32_t olen, seq_nr_t seq_nr, sender_id_t sender_id, mux_t mux)
+{
+  if(!c || !c->params_) {
+    log_printf(ERROR, "cipher not initialized");
+    return -1;
+  }
+
+  if(!kd) {
+    log_printf(ERROR, "no key derivation supplied");
+    return -1;
+  }
+
+  cipher_aesctr_param_t* params = c->params_;
+
+  int ret = key_derivation_generate(kd, dir, LABEL_ENC, seq_nr, c->key_.buf_, c->key_.length_);
+  if(ret < 0)
+    return ret;
+  
+#ifdef USE_SSL_CRYPTO
+  ret = AES_set_encrypt_key(c->key_.buf_, c->key_length_, &params->aes_key_);
+  if(ret) {
+    log_printf(ERROR, "failed to set cipher ssl aes-key (code: %d)", ret);
+    return -1;
+  }
+#else
+  gcry_error_t err = gcry_cipher_setkey(params->handle_, c->key_.buf_, c->key_.length_);
+  if(err) {
+    log_printf(ERROR, "failed to set cipher key: %s", gcry_strerror(err));
+    return -1;
+  }
+#endif
+
+  ret = cipher_aesctr_calc_ctr(c, kd, dir, seq_nr, sender_id, mux);
+  if(ret < 0) {
+    log_printf(ERROR, "failed to calculate cipher CTR");
+    return ret;
+  }
+  
+#ifndef USE_SSL_CRYPTO
+  err = gcry_cipher_setctr(params->handle_, params->ctr_.buf_, C_AESCTR_CTR_LENGTH);
+  if(err) {
+    log_printf(ERROR, "failed to set cipher CTR: %s", gcry_strerror(err));
+    return -1;
+  }
+
+  err = gcry_cipher_encrypt(params->handle_, out, olen, in, ilen);
+  if(err) {
+    log_printf(ERROR, "failed to de/encrypt packet: %s", gcry_strerror(err));
+    return -1;
+  }
+#else
+  if(C_AESCTR_CTR_LENGTH != AES_BLOCK_SIZE) {
+    log_printf(ERROR, "failed to set cipher CTR: size don't fits");
+    return -1;
+  }
+  u_int32_t num = 0;
+  memset(params->ecount_buf_, 0, AES_BLOCK_SIZE);
+  AES_ctr128_encrypt(in, out, (ilen < olen) ? ilen : olen, &params->aes_key_, params->ctr_.buf_, params->ecount_buf_, &num);
+#endif
+
+  return (ilen < olen) ? ilen : olen;  
+}
+#endif
diff --git a/src/cipher.h b/src/cipher.h
new file mode 100644 (file)
index 0000000..f53e412
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ *  uAnytun
+ *
+ *  uAnytun is a tiny implementation of SATP. Unlike Anytun which is a full
+ *  featured implementation uAnytun has no support for multiple connections
+ *  or synchronisation. It is a small single threaded implementation intended
+ *  to act as a client on small platforms.
+ *  The secure anycast tunneling protocol (satp) defines a protocol used
+ *  for communication between any combination of unicast and anycast
+ *  tunnel endpoints.  It has less protocol overhead than IPSec in Tunnel
+ *  mode and allows tunneling of every ETHER TYPE protocol (e.g.
+ *  ethernet, ip, arp ...). satp directly includes cryptography and
+ *  message authentication based on the methodes used by SRTP.  It is
+ *  intended to deliver a generic, scaleable and secure solution for
+ *  tunneling and relaying of packets of any protocol.
+ *  
+ *
+ *  Copyright (C) 2007-2008 Christian Pointner <equinox@anytun.org>
+ *
+ *  This file is part of uAnytun.
+ *
+ *  uAnytun is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 3 as
+ *  published by the Free Software Foundation.
+ *
+ *  uAnytun 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 uAnytun. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _CIPHER_H_
+#define _CIPHER_H_
+
+#ifndef NO_CRYPT
+#ifndef USE_SSL_CRYPTO
+#include <gcrypt.h>
+#else
+#include <openssl/aes.h>
+#endif
+#include "key_derivation.h"
+#else
+enum key_derivation_dir_enum { kd_inbound = 0, kd_outbound = 1 };
+typedef enum key_derivation_dir_enum key_derivation_dir_t;
+typedef u_int8_t key_derivation_t;
+#endif
+
+enum cipher_type_enum { c_unknown, c_null, c_aes_ctr };
+typedef enum cipher_type_enum cipher_type_t;
+
+struct cipher_struct {
+  cipher_type_t type_;
+  u_int16_t key_length_;
+  buffer_t key_;
+  buffer_t salt_;
+  void* params_;
+};
+typedef struct cipher_struct cipher_t;
+
+int cipher_init(cipher_t* c, const char* type);
+void cipher_close(cipher_t* c);
+
+int cipher_encrypt(cipher_t* c, key_derivation_t* kd, key_derivation_dir_t dir, plain_packet_t* in, encrypted_packet_t* out, seq_nr_t seq_nr, sender_id_t sender_id, mux_t mux);
+int cipher_decrypt(cipher_t* c, key_derivation_t* kd, key_derivation_dir_t dir, encrypted_packet_t* in, plain_packet_t* out);
+
+int32_t cipher_null_crypt(u_int8_t* in, u_int32_t ilen, u_int8_t* out, u_int32_t olen);
+
+
+#ifndef NO_CRYPT
+
+#define C_AESCTR_DEFAULT_KEY_LENGTH 128
+#define C_AESCTR_CTR_LENGTH 16
+#define C_AESCTR_SALT_LENGTH 14
+
+union __attribute__((__packed__)) cipher_aesctr_ctr_union {
+  u_int8_t buf_[C_AESCTR_CTR_LENGTH];
+  struct __attribute__ ((__packed__)) {
+    u_int8_t buf_[C_AESCTR_SALT_LENGTH];
+    u_int16_t zero_;
+  } salt_;
+  struct __attribute__((__packed__)) {
+    u_int8_t fill_[C_AESCTR_SALT_LENGTH - sizeof(mux_t) - sizeof(sender_id_t) - 2*sizeof(u_int8_t) - sizeof(seq_nr_t)];
+    mux_t mux_;
+    sender_id_t sender_id_;
+    u_int8_t empty_[2];
+    seq_nr_t seq_nr_;
+    u_int16_t zero_;
+  } params_;
+};
+typedef union cipher_aesctr_ctr_union cipher_aesctr_ctr_t;
+
+struct cipher_aesctr_param_struct {
+#ifndef USE_SSL_CRYPTO
+  gcry_cipher_hd_t handle_;
+#else
+  AES_KEY aes_key_;
+  u_int8_t ecount_buf_[AES_BLOCK_SIZE];
+#endif
+  cipher_aesctr_ctr_t ctr_;
+};
+typedef struct cipher_aesctr_param_struct cipher_aesctr_param_t;
+
+int cipher_aesctr_init(cipher_t* c);
+void cipher_aesctr_close(cipher_t* c);
+int cipher_aesctr_calc_ctr(cipher_t* c, key_derivation_t* kd, key_derivation_dir_t dir, seq_nr_t seq_nr, sender_id_t sender_id, mux_t mux);
+int32_t cipher_aesctr_crypt(cipher_t* c, key_derivation_t* kd, key_derivation_dir_t dir, u_int8_t* in, u_int32_t ilen, u_int8_t* out, u_int32_t olen, seq_nr_t seq_nr, sender_id_t sender_id, mux_t mux);
+#endif
+
+#endif
diff --git a/src/configure b/src/configure
new file mode 100755 (executable)
index 0000000..d88e333
--- /dev/null
@@ -0,0 +1,183 @@
+#!/bin/sh
+#
+#  uAnytun
+#
+#  uAnytun is a tiny implementation of SATP. Unlike Anytun which is a full
+#  featured implementation uAnytun has no support for multiple connections
+#  or synchronisation. It is a small single threaded implementation intended
+#  to act as a client on small platforms.
+#  The secure anycast tunneling protocol (satp) defines a protocol used
+#  for communication between any combination of unicast and anycast
+#  tunnel endpoints.  It has less protocol overhead than IPSec in Tunnel
+#  mode and allows tunneling of every ETHER TYPE protocol (e.g.
+#  ethernet, ip, arp ...). satp directly includes cryptography and
+#  message authentication based on the methodes used by SRTP.  It is
+#  intended to deliver a generic, scaleable and secure solution for
+#  tunneling and relaying of packets of any protocol.
+#  
+#
+#  Copyright (C) 2007-2008 Christian Pointner <equinox@anytun.org>
+#
+#  This file is part of uAnytun.
+#
+#  uAnytun is free software: you can redistribute it and/or modify
+#  it under the terms of the GNU General Public License version 3 as
+#  published by the Free Software Foundation.
+#
+#  uAnytun 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 uAnytun. If not, see <http://www.gnu.org/licenses/>.
+#
+
+TARGET=`uname -s`
+
+CFLAGS='-g -O2'
+LDFLAGS='-g -Wall -O2'
+
+CRYPTO_LIB='gcrypt'
+PASSPHRASE=1
+V4_MAPPED=1
+
+PREFIX='/usr/local'
+USERNAME='uanytun'
+USERHOME='/var/run/uanytun'
+
+print_usage() {
+  echo "configure --help                    print this"
+  echo "          --target=<TARGET>         build target i.e. Linux (default: autodetect)"
+  echo "          --prefix=<PREFIX>         the installation prefix (default: /usr/local)"
+  echo "          --username=<USERNAME>     create this user when installing (default: uanytun)"
+  echo "          --userhome=<PATH>         the home directory of the user to be created  (default: /var/run/uanytun)"
+  echo "          --use-ssl-crypto          use ssl crypto library instead of libgcrypt"
+  echo "          --no-crypto               disable crypto at all (only NULL cipher)"
+  echo "          --disable-passphrase      disable master key and salt passphrase"
+  echo "          --enable-passphrase       enable master key and salt passphrase"
+  echo "          --disable-v4-mapped       disable V4-Mapped addresses (this means to disable"
+  echo "                                    simultanious use of IPv4 and IPv6)"
+  echo "          --enable-v4-mapped        enable V4-Mapped addresses"
+}
+
+for arg
+do
+  case $arg in
+  --target=*)
+    TARGET=${arg#--target=}
+  ;;
+  --prefix=*)
+    PREFIX=${arg#--prefix=}
+  ;;
+  --username=*)
+    USERNAME=${arg#--username=}
+  ;;
+  --userhome=*)
+    USERHOME=${arg#--userhome=}
+  ;;
+  --use-ssl-crypto)
+    CRYPTO_LIB='ssl'
+  ;;
+  --no-crypto)
+    CRYPTO_LIB='none'
+  ;; 
+  --disable-passphrase)
+    PASSPHRASE=0
+  ;;
+  --enable-passphrase)
+    PASSPHRASE=1
+  ;;
+  --disable-v4-mapped)
+    V4_MAPPED=0 
+  ;; 
+  --enable-v4-mapped)
+    V4_MAPPED=2
+  ;; 
+  --help)
+    print_usage
+    exit 0
+  ;;
+  *)
+    echo "Unknown argument: $arg"
+    print_usage
+    exit 1
+  ;;
+  esac
+done
+
+rm -f include.mk
+case $TARGET in 
+  Linux)
+    rm -f tun.c
+    ln -sf linux/tun.c
+    echo "loading Linux specific TUN Device"
+  ;;
+  OpenBSD|FreeBSD|NetBSD)
+    rm -f tun.c
+    ln -sf bsd/tun.c
+    echo "loading BSD specific TUN Device"
+    CFLAGS=$CFLAGS' -I/usr/local/include'
+    LDFLAGS=$LDFLAGS' -L/usr/local/lib'
+    if [ $V4_MAPPED -ne 2 ]; then
+      V4_MAPPED=0
+    fi
+  ;;
+  *)
+    echo "Plattform not supported"
+    exit 1;
+  ;;
+esac
+
+
+case $CRYPTO_LIB in
+  gcrypt)
+    LDFLAGS=$LDFLAGS' -lgcrypt'
+    echo "using libgcrypt library"
+  ;;
+  ssl)
+    CFLAGS=$CFLAGS' -DUSE_SSL_CRYPTO'
+    LDFLAGS=$LDFLAGS' -lcrypto'
+    echo "using ssl crypto library"
+  ;;
+  none)
+    CFLAGS=$CFLAGS' -DNO_CRYPT'
+    echo "NO_CRYPT_OBJ = 1" >> include.mk
+    echo "disabling crypto"
+  ;;
+esac
+
+if [ $PASSPHRASE -eq 0 ]; then
+  CFLAGS=$CFLAGS' -DNO_PASSPHRASE'
+  echo "disabling master key and salt passphrase"
+fi
+
+if [ $V4_MAPPED -eq 0 ]; then
+  CFLAGS=$CFLAGS' -DNO_V4MAPPED'
+  echo "WARNING: disabling V4 mapped addresses, this prevents uanytun from using IPv6 and IPv4 Sockets at the same time"
+fi
+
+if [ "x$PREFIX" = "x/usr" ]; then
+ ETCDIR=/etc
+else
+ ETCDIR=$PREFIX/etc
+fi
+
+cat >> include.mk <<EOF
+# this file was created automatically
+# do not edit this file directly 
+# use ./configure instead
+
+TARGET := $TARGET
+CC := gcc
+CFLAGS := $CFLAGS
+LDFLAGS := $LDFLAGS
+
+SBINDIR := $PREFIX/sbin
+MANDIR := $PREFIX/share/man
+ETCDIR := $ETCDIR
+USERNAME := $USERNAME
+USERHOME := $USERHOME
+EOF
+
+exit 0
diff --git a/src/daemon.h b/src/daemon.h
new file mode 100644 (file)
index 0000000..ac0516e
--- /dev/null
@@ -0,0 +1,172 @@
+/*
+ *  uAnytun
+ *
+ *  uAnytun is a tiny implementation of SATP. Unlike Anytun which is a full
+ *  featured implementation uAnytun has no support for multiple connections
+ *  or synchronisation. It is a small single threaded implementation intended
+ *  to act as a client on small platforms.
+ *  The secure anycast tunneling protocol (satp) defines a protocol used
+ *  for communication between any combination of unicast and anycast
+ *  tunnel endpoints.  It has less protocol overhead than IPSec in Tunnel
+ *  mode and allows tunneling of every ETHER TYPE protocol (e.g.
+ *  ethernet, ip, arp ...). satp directly includes cryptography and
+ *  message authentication based on the methodes used by SRTP.  It is
+ *  intended to deliver a generic, scaleable and secure solution for
+ *  tunneling and relaying of packets of any protocol.
+ *  
+ *
+ *  Copyright (C) 2007-2008 Christian Pointner <equinox@anytun.org>
+ *
+ *  This file is part of uAnytun.
+ *
+ *  uAnytun is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 3 as
+ *  published by the Free Software Foundation.
+ *
+ *  uAnytun 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 uAnytun. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _DAEMON_H_
+#define _DAEMON_H_
+
+#include <poll.h>
+#include <fcntl.h>
+#include <pwd.h>
+#include <grp.h>
+#include <sys/wait.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+struct priv_info_struct {
+  struct passwd* pw_;
+  struct group* gr_;
+};
+typedef struct priv_info_struct priv_info_t;
+
+int priv_init(priv_info_t* priv, const char* username, const char* groupname)
+{
+  if(!priv)
+    return -1;
+
+  priv->pw_ = NULL;
+  priv->gr_ = NULL;
+
+  priv->pw_ = getpwnam(username);
+  if(!priv->pw_) {
+    log_printf(ERROR, "unkown user %s", username);
+    return -1;
+  }
+
+  if(groupname)
+    priv->gr_ = getgrnam(groupname);
+  else
+    priv->gr_ = getgrgid(priv->pw_->pw_gid);
+
+  if(!priv->gr_) {
+    log_printf(ERROR, "unkown group %s", groupname);
+    return -1;
+  }
+
+  return 0;
+}
+
+int priv_drop(priv_info_t* priv)
+{
+  if(!priv || !priv->pw_ || !priv->gr_) {
+    log_printf(ERROR, "privileges not initialized properly");
+    return -1;
+  }
+
+  if(setgid(priv->gr_->gr_gid))  {
+    log_printf(ERROR, "setgid('%s') failed: %s", priv->gr_->gr_name, strerror(errno));
+    return -1;
+  }
+
+  gid_t gr_list[1];
+  gr_list[0] = priv->gr_->gr_gid;
+  if(setgroups (1, gr_list)) {
+    log_printf(ERROR, "setgroups(['%s']) failed: %s", priv->gr_->gr_name, strerror(errno));
+    return -1;
+  }
+
+  if(setuid(priv->pw_->pw_uid)) {
+    log_printf(ERROR, "setuid('%s') failed: %s", priv->pw_->pw_name, strerror(errno));
+    return -1;
+  }
+
+  log_printf(NOTICE, "dropped privileges to %s:%s", priv->pw_->pw_name, priv->gr_->gr_name);
+  return 0;
+}
+
+
+int do_chroot(const char* chrootdir)
+{
+  if(getuid() != 0) {
+    log_printf(ERROR, "this programm has to be run as root in order to run in a chroot");
+    return -1;
+  }
+
+  if(chroot(chrootdir)) {
+    log_printf(ERROR, "can't chroot to %s: %s", chrootdir, strerror(errno));
+    return -1;
+  }
+  log_printf(NOTICE, "we are in chroot jail (%s) now", chrootdir);
+  if(chdir("/")) {
+    log_printf(ERROR, "can't change to /: %s", strerror(errno));
+    return -1;
+  }
+}
+
+void daemonize()
+{
+  pid_t pid;
+
+  pid = fork();
+  if(pid < 0) {
+    log_printf(ERROR, "daemonizing failed at fork(): %s, exitting", strerror(errno));
+    exit(-1);
+  }
+  if(pid) exit(0);
+
+  umask(0);
+
+  if(setsid() < 0) {
+    log_printf(ERROR, "daemonizing failed at setsid(): %s, exitting", strerror(errno));
+    exit(-1);
+  }
+
+  pid = fork();
+  if(pid < 0) {
+    log_printf(ERROR, "daemonizing failed at fork(): %s, exitting", strerror(errno));
+    exit(-1);
+  }
+  if(pid) exit(0);
+
+  if ((chdir("/")) < 0) {
+    log_printf(ERROR, "daemonizing failed at chdir(): %s, exitting", strerror(errno));
+    exit(-1);
+  }
+
+  int fd;
+  for (fd=0;fd<=2;fd++) // close all file descriptors
+    close(fd);
+  fd = open("/dev/null",O_RDWR);        // stdin
+  if(fd == -1)
+    log_printf(WARNING, "can't open stdin (chroot and no link to /dev/null?)");
+  else {
+    if(dup(fd) == -1)   // stdout
+      log_printf(WARNING, "can't open stdout");
+    if(dup(fd) == -1)   // stderr
+      log_printf(WARNING, "can't open stderr");
+  }
+  umask(027);
+}
+
+#endif
+
diff --git a/src/datatypes.h b/src/datatypes.h
new file mode 100644 (file)
index 0000000..3925f26
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ *  uAnytun
+ *
+ *  uAnytun is a tiny implementation of SATP. Unlike Anytun which is a full
+ *  featured implementation uAnytun has no support for multiple connections
+ *  or synchronisation. It is a small single threaded implementation intended
+ *  to act as a client on small platforms.
+ *  The secure anycast tunneling protocol (satp) defines a protocol used
+ *  for communication between any combination of unicast and anycast
+ *  tunnel endpoints.  It has less protocol overhead than IPSec in Tunnel
+ *  mode and allows tunneling of every ETHER TYPE protocol (e.g.
+ *  ethernet, ip, arp ...). satp directly includes cryptography and
+ *  message authentication based on the methodes used by SRTP.  It is
+ *  intended to deliver a generic, scaleable and secure solution for
+ *  tunneling and relaying of packets of any protocol.
+ *  
+ *
+ *  Copyright (C) 2007-2008 Christian Pointner <equinox@anytun.org>
+ *
+ *  This file is part of uAnytun.
+ *
+ *  uAnytun is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 3 as
+ *  published by the Free Software Foundation.
+ *
+ *  uAnytun 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 uAnytun. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _DATATYPES_H_
+#define _DATATYPES_H_
+
+#include <stdint.h>
+#include <arpa/inet.h>
+
+typedef uint8_t u_int8_t;
+typedef uint16_t u_int16_t;
+typedef uint32_t u_int32_t;
+typedef uint64_t u_int64_t;
+/* typedef int8_t int8_t; */
+/* typedef int16_t int16_t; */
+/* typedef int32_t int32_t; */
+/* typedef int64_t int64_t; */
+
+typedef u_int32_t window_size_t;
+
+typedef u_int32_t seq_nr_t;
+#define SEQ_NR_T_NTOH(a) ntohl(a)
+#define SEQ_NR_T_HTON(a) htonl(a)
+#define SEQ_NR_MAX UINT32_MAX
+
+typedef u_int16_t sender_id_t;
+#define SENDER_ID_T_NTOH(a) ntohs(a)
+#define SENDER_ID_T_HTON(a) htons(a)
+
+typedef u_int16_t payload_type_t;
+#define PAYLOAD_TYPE_T_NTOH(a) ntohs(a)
+#define PAYLOAD_TYPE_T_HTON(a) htons(a)
+
+typedef u_int16_t mux_t;
+#define MUX_T_NTOH(a) ntohs(a)
+#define MUX_T_HTON(a) htons(a)
+
+typedef u_int32_t satp_prf_label_t;
+#define SATP_PRF_LABEL_T_NTOH(a) ntohl(a)
+#define SATP_PRF_LABEL_T_HTON(a) htonl(a)
+
+struct buffer_struct {
+  u_int32_t length_;
+  u_int8_t* buf_;
+};
+typedef struct buffer_struct buffer_t;
+
+#endif
diff --git a/src/encrypted_packet.c b/src/encrypted_packet.c
new file mode 100644 (file)
index 0000000..53387f3
--- /dev/null
@@ -0,0 +1,200 @@
+/*
+ *  uAnytun
+ *
+ *  uAnytun is a tiny implementation of SATP. Unlike Anytun which is a full
+ *  featured implementation uAnytun has no support for multiple connections
+ *  or synchronisation. It is a small single threaded implementation intended
+ *  to act as a client on small platforms.
+ *  The secure anycast tunneling protocol (satp) defines a protocol used
+ *  for communication between any combination of unicast and anycast
+ *  tunnel endpoints.  It has less protocol overhead than IPSec in Tunnel
+ *  mode and allows tunneling of every ETHER TYPE protocol (e.g.
+ *  ethernet, ip, arp ...). satp directly includes cryptography and
+ *  message authentication based on the methodes used by SRTP.  It is
+ *  intended to deliver a generic, scaleable and secure solution for
+ *  tunneling and relaying of packets of any protocol.
+ *  
+ *
+ *  Copyright (C) 2007-2008 Christian Pointner <equinox@anytun.org>
+ *
+ *  This file is part of uAnytun.
+ *
+ *  uAnytun is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 3 as
+ *  published by the Free Software Foundation.
+ *
+ *  uAnytun 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 uAnytun. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "datatypes.h"
+
+#include "encrypted_packet.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+void encrypted_packet_init(encrypted_packet_t* packet, u_int32_t auth_tag_length)
+{
+  if(!packet)
+    return;
+
+  memset (packet, 0, sizeof(*packet));
+  if(auth_tag_length > (ENCRYPTED_PACKET_SIZE_MAX - sizeof(encrypted_packet_header_t)))
+    packet->auth_tag_length_ = ENCRYPTED_PACKET_SIZE_MAX - sizeof(encrypted_packet_header_t);
+  else
+    packet->auth_tag_length_ = auth_tag_length;
+}
+
+u_int32_t encrypted_packet_get_minimum_length(encrypted_packet_t* packet)
+{
+  if(!packet)
+    return 0;
+
+  return (sizeof(encrypted_packet_header_t) + packet->auth_tag_length_);
+}
+
+u_int8_t* encrypted_packet_get_packet(encrypted_packet_t* packet)
+{
+  if(!packet)
+    return NULL;
+
+  return packet->data_.buf_;
+}
+
+u_int32_t encrypted_packet_get_length(encrypted_packet_t* packet)
+{
+  if(!packet)
+    return 0;
+
+  return (packet->payload_length_ + sizeof(encrypted_packet_header_t) + packet->auth_tag_length_);
+}
+
+void encrypted_packet_set_length(encrypted_packet_t* packet, u_int32_t len)
+{
+  if(!packet)
+    return;
+
+  if(len > ENCRYPTED_PACKET_SIZE_MAX)
+    len = ENCRYPTED_PACKET_SIZE_MAX - sizeof(encrypted_packet_header_t) - packet->auth_tag_length_;
+  else if(len < (sizeof(encrypted_packet_header_t) + packet->auth_tag_length_))
+    len = 0;
+  else
+    len -= (sizeof(encrypted_packet_header_t) + packet->auth_tag_length_);
+
+  packet->payload_length_ = len;
+}
+
+u_int8_t* encrypted_packet_get_payload(encrypted_packet_t* packet)
+{
+  if(!packet || !packet->payload_length_)
+    return NULL;
+
+  return (packet->data_.buf_ + sizeof(encrypted_packet_header_t));
+}
+
+u_int32_t encrypted_packet_get_payload_length(encrypted_packet_t* packet)
+{
+  if(!packet)
+    return 0;
+
+  return packet->payload_length_;
+}
+
+void encrypted_packet_set_payload_length(encrypted_packet_t* packet, u_int32_t len)
+{
+  if(!packet)
+    return;
+
+  if(len > (ENCRYPTED_PACKET_SIZE_MAX - sizeof(encrypted_packet_header_t) - packet->auth_tag_length_))
+    len = ENCRYPTED_PACKET_SIZE_MAX - sizeof(encrypted_packet_header_t) - packet->auth_tag_length_;
+
+  packet->payload_length_ = len;
+}
+
+u_int8_t* encrypted_packet_get_auth_portion(encrypted_packet_t* packet)
+{
+  if(!packet)
+    return NULL;
+
+  return packet->data_.buf_;
+}
+
+u_int32_t encrypted_packet_get_auth_portion_length(encrypted_packet_t* packet)
+{
+  if(!packet)
+    return 0;
+
+  return  packet->payload_length_ + sizeof(encrypted_packet_header_t);
+}
+
+
+u_int8_t* encrypted_packet_get_auth_tag(encrypted_packet_t* packet)
+{
+  if(!packet || !packet->auth_tag_length_)
+    return NULL;
+
+  return (packet->data_.buf_ + sizeof(encrypted_packet_header_t) + packet->payload_length_);
+}
+
+u_int32_t encrypted_packet_get_auth_tag_length(encrypted_packet_t* packet)
+{
+  if(!packet)
+    return 0;
+
+  return packet->auth_tag_length_;
+}
+
+
+seq_nr_t encrypted_packet_get_seq_nr(encrypted_packet_t* packet)
+{
+  if(!packet)
+    return 0;
+
+  return SEQ_NR_T_NTOH(packet->data_.header_.seq_nr_);
+}
+
+void encrypted_packet_set_seq_nr(encrypted_packet_t* packet, seq_nr_t seq_nr)
+{
+  if(!packet)
+    return;
+
+  packet->data_.header_.seq_nr_ = SEQ_NR_T_HTON(seq_nr);
+}
+
+sender_id_t encrypted_packet_get_sender_id(encrypted_packet_t* packet)
+{
+  if(!packet)
+    return 0;
+
+  return SENDER_ID_T_NTOH(packet->data_.header_.sender_id_);
+}
+
+void encrypted_packet_set_sender_id(encrypted_packet_t* packet, sender_id_t sender_id)
+{
+  if(!packet)
+    return;
+
+  packet->data_.header_.sender_id_ = SENDER_ID_T_HTON(sender_id);
+}
+
+mux_t encrypted_packet_get_mux(encrypted_packet_t* packet)
+{
+  if(!packet)
+    return 0;
+  
+  return MUX_T_NTOH(packet->data_.header_.mux_);
+}
+
+void encrypted_packet_set_mux(encrypted_packet_t* packet, mux_t mux)
+{
+  if(!packet)
+    return;
+
+  packet->data_.header_.mux_ = MUX_T_HTON(mux);
+}
diff --git a/src/encrypted_packet.h b/src/encrypted_packet.h
new file mode 100644 (file)
index 0000000..e9cdc59
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ *  uAnytun
+ *
+ *  uAnytun is a tiny implementation of SATP. Unlike Anytun which is a full
+ *  featured implementation uAnytun has no support for multiple connections
+ *  or synchronisation. It is a small single threaded implementation intended
+ *  to act as a client on small platforms.
+ *  The secure anycast tunneling protocol (satp) defines a protocol used
+ *  for communication between any combination of unicast and anycast
+ *  tunnel endpoints.  It has less protocol overhead than IPSec in Tunnel
+ *  mode and allows tunneling of every ETHER TYPE protocol (e.g.
+ *  ethernet, ip, arp ...). satp directly includes cryptography and
+ *  message authentication based on the methodes used by SRTP.  It is
+ *  intended to deliver a generic, scaleable and secure solution for
+ *  tunneling and relaying of packets of any protocol.
+ *  
+ *
+ *  Copyright (C) 2007-2008 Christian Pointner <equinox@anytun.org>
+ *
+ *  This file is part of uAnytun.
+ *
+ *  uAnytun is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 3 as
+ *  published by the Free Software Foundation.
+ *
+ *  uAnytun 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 uAnytun. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _ENCRYPTED_PACKET_H_
+#define _ENCRYPTED_PACKET_H_
+
+#define ENCRYPTED_PACKET_SIZE_MAX 1600
+
+#define PAYLOAD_TYPE_TAP 0x6558
+#define PAYLOAD_TYPE_TUN 0x0000
+#define PAYLOAD_TYPE_TUN4 0x0800
+#define PAYLOAD_TYPE_TUN6 0x86DD
+
+struct __attribute__ ((__packed__)) encrypted_packet_header_struct {
+  seq_nr_t seq_nr_;
+  sender_id_t sender_id_;
+  mux_t mux_;
+};
+typedef struct encrypted_packet_header_struct encrypted_packet_header_t;
+
+struct encrypted_packet_struct {
+  u_int32_t payload_length_;
+  u_int32_t auth_tag_length_;
+  union __attribute__ ((__packed__)) {
+    u_int8_t buf_[ENCRYPTED_PACKET_SIZE_MAX];
+    encrypted_packet_header_t header_;
+ } data_;
+};
+typedef struct encrypted_packet_struct encrypted_packet_t;
+
+void encrypted_packet_init(encrypted_packet_t* packet, u_int32_t auth_tag_length);
+
+u_int32_t encrypted_packet_get_minimum_length(encrypted_packet_t* packet);
+
+u_int8_t* encrypted_packet_get_packet(encrypted_packet_t* packet);
+u_int32_t encrypted_packet_get_length(encrypted_packet_t* packet);
+void encrypted_packet_set_length(encrypted_packet_t* packet, u_int32_t len);
+
+u_int8_t* encrypted_packet_get_payload(encrypted_packet_t* packet);
+u_int32_t encrypted_packet_get_payload_length(encrypted_packet_t* packet);
+void encrypted_packet_set_payload_length(encrypted_packet_t* packet, u_int32_t len);
+
+u_int8_t* encrypted_packet_get_auth_portion(encrypted_packet_t* packet);
+u_int32_t encrypted_packet_get_auth_portion_length(encrypted_packet_t* packet);
+
+u_int8_t* encrypted_packet_get_auth_tag(encrypted_packet_t* packet);
+u_int32_t encrypted_packet_get_auth_tag_length(encrypted_packet_t* packet);
+
+seq_nr_t encrypted_packet_get_seq_nr(encrypted_packet_t* packet);
+void encrypted_packet_set_seq_nr(encrypted_packet_t* packet, seq_nr_t seq_nr);
+
+sender_id_t encrypted_packet_get_sender_id(encrypted_packet_t* packet);
+void encrypted_packet_set_sender_id(encrypted_packet_t* packet, sender_id_t sender_id);
+
+mux_t encrypted_packet_get_mux(encrypted_packet_t* packet);
+void encrypted_packet_set_mux(encrypted_packet_t* packet, mux_t mux);
+
+
+#endif
diff --git a/src/key_derivation.c b/src/key_derivation.c
new file mode 100644 (file)
index 0000000..e9ab15f
--- /dev/null
@@ -0,0 +1,462 @@
+/*
+ *  uAnytun
+ *
+ *  uAnytun is a tiny implementation of SATP. Unlike Anytun which is a full
+ *  featured implementation uAnytun has no support for multiple connections
+ *  or synchronisation. It is a small single threaded implementation intended
+ *  to act as a client on small platforms.
+ *  The secure anycast tunneling protocol (satp) defines a protocol used
+ *  for communication between any combination of unicast and anycast
+ *  tunnel endpoints.  It has less protocol overhead than IPSec in Tunnel
+ *  mode and allows tunneling of every ETHER TYPE protocol (e.g.
+ *  ethernet, ip, arp ...). satp directly includes cryptography and
+ *  message authentication based on the methodes used by SRTP.  It is
+ *  intended to deliver a generic, scaleable and secure solution for
+ *  tunneling and relaying of packets of any protocol.
+ *  
+ *
+ *  Copyright (C) 2007-2008 Christian Pointner <equinox@anytun.org>
+ *
+ *  This file is part of uAnytun.
+ *
+ *  uAnytun is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 3 as
+ *  published by the Free Software Foundation.
+ *
+ *  uAnytun 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 uAnytun. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "datatypes.h"
+
+#include "key_derivation.h"
+
+#ifdef USE_SSL_CRYPTO
+#include <openssl/sha.h>
+#endif
+
+#include "log.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+int key_derivation_init(key_derivation_t* kd, const char* type, role_t role, const char* passphrase, u_int8_t* key, u_int32_t key_len, u_int8_t* salt, u_int32_t salt_len)
+{
+  if(!kd) 
+    return -1;
+
+  kd->role_ = role;
+  kd->key_length_ = 0;
+
+  kd->type_ = kd_unknown;
+  if(!strcmp(type, "null"))
+    kd->type_ = kd_null;
+  else if(!strncmp(type, "aes-ctr", 7)) {
+    kd->type_ = kd_aes_ctr;
+    if(type[7] == 0) {
+      kd->key_length_ = KD_AESCTR_DEFAULT_KEY_LENGTH;
+    }
+    else if(type[7] != '-') 
+      return -1;
+    else {
+      const char* tmp = &type[8];
+      kd->key_length_ = atoi(tmp);
+    }
+  }
+  else {
+    log_printf(ERROR, "unknown key derivation type");
+    return -1;
+  }
+
+  switch(role) {
+  case ROLE_LEFT: log_printf(NOTICE, "key derivation role: left"); break;
+  case ROLE_RIGHT: log_printf(NOTICE, "key derivation role: right"); break;
+  default: log_printf(NOTICE, "key derivation role: unknown"); break;
+  }
+  kd->params_ = NULL;
+
+  if(!key) {
+    kd->master_key_.buf_ = NULL;
+    kd->master_key_.length_ = 0;
+  }
+  else {
+    kd->master_key_.buf_ = malloc(key_len);
+    if(!kd->master_key_.buf_)
+      return -2;
+    memcpy(kd->master_key_.buf_, key, key_len);
+    kd->master_key_.length_ = key_len;
+  }
+
+  if(!salt) {
+    kd->master_salt_.buf_ = NULL;
+    kd->master_salt_.length_ = 0;
+  }
+  else {
+    kd->master_salt_.buf_ = malloc(salt_len);
+    if(!kd->master_salt_.buf_) {
+      if(kd->master_key_.buf_)
+        free(kd->master_key_.buf_);
+      return -2;
+    }
+    memcpy(kd->master_salt_.buf_, salt, salt_len);
+    kd->master_salt_.length_ = salt_len;
+  }
+
+  int ret = 0;
+  if(kd->type_ == kd_aes_ctr)
+    ret = key_derivation_aesctr_init(kd, passphrase);
+
+  if(ret)
+    key_derivation_close(kd);
+
+  return ret;
+}
+
+#ifndef NO_PASSPHRASE
+int key_derivation_generate_master_key(key_derivation_t* kd, const char* passphrase, u_int16_t key_length)
+{
+  if(!kd || !passphrase)
+    return -1;
+
+  if(kd->master_key_.buf_) {
+    log_printf(WARNING, "master key and passphrase provided, ignoring passphrase");
+    return 0;
+  }    
+  log_printf(NOTICE, "using passphrase to generate master key");
+
+  if(!key_length || (key_length % 8)) {
+    log_printf(ERROR, "bad master key length");
+    return -1;
+  }
+
+#ifndef USE_SSL_CRYPTO
+  if(key_length > (gcry_md_get_algo_dlen(GCRY_MD_SHA256) * 8)) {
+#else
+  if(key_length > (SHA256_DIGEST_LENGTH * 8)) {
+#endif
+    log_printf(ERROR, "master key too long for passphrase algorithm");
+    return -1;
+  }
+
+  buffer_t digest;
+#ifndef USE_SSL_CRYPTO
+  digest.length_ = gcry_md_get_algo_dlen(GCRY_MD_SHA256);
+#else
+  digest.length_ = SHA256_DIGEST_LENGTH;
+#endif
+  digest.buf_ = malloc(digest.length_);
+  if(!digest.buf_)
+    return -2;
+
+
+#ifndef USE_SSL_CRYPTO
+  gcry_md_hash_buffer(GCRY_MD_SHA256, digest.buf_, passphrase, strlen(passphrase));
+#else
+  SHA256(passphrase, strlen(passphrase), digest.buf_);
+#endif
+
+  kd->master_key_.length_ = key_length/8;
+  kd->master_key_.buf_ = malloc(kd->master_key_.length_);
+  if(!kd->master_key_.buf_) {
+    kd->master_key_.length_ = 0;
+    free(digest.buf_);
+    return -2;
+  }
+
+  memcpy(kd->master_key_.buf_, &digest.buf_[digest.length_ - kd->master_key_.length_], kd->master_key_.length_);
+  free(digest.buf_);
+
+  return 0;
+}
+
+int key_derivation_generate_master_salt(key_derivation_t* kd, const char* passphrase, u_int16_t salt_length)
+{
+  if(!kd || !passphrase)
+    return -1;
+
+  if(kd->master_salt_.buf_) {
+    log_printf(WARNING, "master salt and passphrase provided, ignoring passphrase");
+    return 0;
+  }    
+  log_printf(NOTICE, "using passphrase to generate master salt");
+
+  if(!salt_length || (salt_length % 8)) {
+    log_printf(ERROR, "bad master salt length");
+    return -1;
+  }
+
+#ifndef USE_SSL_CRYPTO
+  if(salt_length > (gcry_md_get_algo_dlen(GCRY_MD_SHA1) * 8)) {
+#else
+  if(salt_length > (SHA_DIGEST_LENGTH * 8)) {
+#endif
+    log_printf(ERROR, "master salt too long for passphrase algorithm");
+    return -1;
+  }
+
+  buffer_t digest;
+#ifndef USE_SSL_CRYPTO
+  digest.length_ = gcry_md_get_algo_dlen(GCRY_MD_SHA1);
+#else
+  digest.length_ = SHA_DIGEST_LENGTH;
+#endif
+  digest.buf_ = malloc(digest.length_);
+  if(!digest.buf_)
+    return -2;
+
+#ifndef USE_SSL_CRYPTO
+  gcry_md_hash_buffer(GCRY_MD_SHA1, digest.buf_, passphrase, strlen(passphrase));
+#else
+  SHA1(passphrase, strlen(passphrase), digest.buf_);
+#endif
+
+  kd->master_salt_.length_ = salt_length/8;
+  kd->master_salt_.buf_ = malloc(kd->master_salt_.length_);
+  if(!kd->master_salt_.buf_) {
+    kd->master_salt_.length_ = 0;
+    free(digest.buf_);
+    return -2;
+  }
+
+  memcpy(kd->master_salt_.buf_, &digest.buf_[digest.length_ - kd->master_salt_.length_], kd->master_salt_.length_);
+  free(digest.buf_);
+
+  return 0;
+}
+#endif
+
+void key_derivation_close(key_derivation_t* kd)
+{
+  if(!kd)
+    return;
+
+  if(kd->type_ == kd_aes_ctr)
+    key_derivation_aesctr_close(kd);
+
+  if(kd->master_key_.buf_)
+    free(kd->master_key_.buf_);
+  if(kd->master_salt_.buf_)
+    free(kd->master_salt_.buf_);
+}
+
+int key_derivation_generate(key_derivation_t* kd, key_derivation_dir_t dir, satp_prf_label_t label, seq_nr_t seq_nr, u_int8_t* key, u_int32_t len)
+{
+  if(!kd || !key) 
+    return -1;
+
+  if(label >= LABEL_NIL) {
+    log_printf(ERROR, "unknown label 0x%02X", label);
+    return -1;
+  }
+
+  int ret = 0;
+  if(kd->type_ == kd_null)
+    ret = key_derivation_null_generate(key, len);
+  else if(kd->type_ == kd_aes_ctr)
+    ret = key_derivation_aesctr_generate(kd, dir, label, seq_nr, key, len);
+  else {
+    log_printf(ERROR, "unknown key derivation type");
+    return -1;
+  }
+  return ret;
+}
+
+satp_prf_label_t convert_label(role_t role, key_derivation_dir_t dir, satp_prf_label_t label)
+{
+  switch(label) {
+  case LABEL_ENC: {
+    if(dir == kd_outbound) {
+      if(role == ROLE_LEFT) return LABEL_LEFT_ENC;
+      if(role == ROLE_RIGHT) return LABEL_RIGHT_ENC;
+    }
+    else {
+      if(role == ROLE_LEFT) return LABEL_RIGHT_ENC;
+      if(role == ROLE_RIGHT) return LABEL_LEFT_ENC;
+    }
+    break;
+  }
+  case LABEL_SALT: {
+    if(dir == kd_outbound) {
+      if(role == ROLE_LEFT) return LABEL_LEFT_SALT;
+      if(role == ROLE_RIGHT) return LABEL_RIGHT_SALT;
+    }
+    else {
+      if(role == ROLE_LEFT) return LABEL_RIGHT_SALT;
+      if(role == ROLE_RIGHT) return LABEL_LEFT_SALT;
+    }
+    break;
+  }
+  case LABEL_AUTH: {
+    if(dir == kd_outbound) {
+      if(role == ROLE_LEFT) return LABEL_LEFT_AUTH;
+      if(role == ROLE_RIGHT) return LABEL_RIGHT_AUTH;
+    }
+    else {
+      if(role == ROLE_LEFT) return LABEL_RIGHT_AUTH;
+      if(role == ROLE_RIGHT) return LABEL_LEFT_AUTH;
+    }
+    break;
+  }
+  }
+
+  return label;
+}
+
+/* ---------------- NULL Key Derivation ---------------- */
+
+int key_derivation_null_generate(u_int8_t* key, u_int32_t len)
+{
+  memset(key, 0, len);
+  return 1;
+}
+
+/* ---------------- AES-Ctr Key Derivation ---------------- */
+
+int key_derivation_aesctr_init(key_derivation_t* kd, const char* passphrase)
+{
+  if(!kd)
+    return -1;
+
+  if(kd->params_)
+    free(kd->params_);
+  kd->params_ = malloc(sizeof(key_derivation_aesctr_param_t));
+  if(!kd->params_)
+    return -2;
+
+  key_derivation_aesctr_param_t* params = kd->params_;
+#ifndef USE_SSL_CRYPTO
+  params->handle_ = 0;
+#endif
+
+#ifndef NO_PASSPHRASE
+  if(passphrase) {
+    int ret = key_derivation_generate_master_key(kd, passphrase, kd->key_length_);
+    if(ret)
+      return ret;
+    ret = key_derivation_generate_master_salt(kd, passphrase, KD_AESCTR_SALT_LENGTH*8);
+    if(ret)
+      return ret;
+  }
+#endif
+
+#ifndef USE_SSL_CRYPTO
+  int algo;
+  switch(kd->key_length_) {
+  case 128: algo = GCRY_CIPHER_AES128; break;
+  case 192: algo = GCRY_CIPHER_AES192; break;
+  case 256: algo = GCRY_CIPHER_AES256; break;
+  default: {
+    log_printf(ERROR, "key derivation key length of %d Bits is not supported", kd->key_length_);
+    return -1;
+  }
+  }
+
+  gcry_error_t err = gcry_cipher_open(&params->handle_, algo, GCRY_CIPHER_MODE_CTR, 0);
+  if(err) {
+    log_printf(ERROR, "failed to open key derivation cipher: %s", gcry_strerror(err));
+    return -1;
+  } 
+
+  err = gcry_cipher_setkey(params->handle_, kd->master_key_.buf_, kd->master_key_.length_);
+  if(err) {
+    log_printf(ERROR, "failed to set key derivation key: %s", gcry_strerror(err));
+    return -1;
+  }
+#else
+  int ret = AES_set_encrypt_key(kd->master_key_.buf_, kd->master_key_.length_*8, &params->aes_key_);
+  if(ret) {
+    log_printf(ERROR, "failed to set key derivation ssl aes-key (code: %d)", ret);
+    return -1;
+  }
+#endif
+
+  return 0;
+}
+
+void key_derivation_aesctr_close(key_derivation_t* kd)
+{
+  if(!kd)
+    return;
+
+  if(kd->params_) {
+    key_derivation_aesctr_param_t* params = kd->params_;
+
+#ifndef USE_SSL_CRYPTO
+    if(params->handle_)
+      gcry_cipher_close(params->handle_);
+#endif
+
+    free(kd->params_);
+  }
+}
+
+int key_derivation_aesctr_calc_ctr(key_derivation_t* kd, key_derivation_dir_t dir, satp_prf_label_t label, seq_nr_t seq_nr)
+{
+  if(!kd || !kd->params_)
+    return -1;
+
+  key_derivation_aesctr_param_t* params = kd->params_;
+
+  if(kd->master_salt_.length_ != KD_AESCTR_SALT_LENGTH) {
+    log_printf(ERROR, "master salt has wrong length");
+    return -1;
+  }
+  memcpy(params->ctr_.salt_.buf_, kd->master_salt_.buf_, KD_AESCTR_SALT_LENGTH);
+  params->ctr_.salt_.zero_ = 0;
+  params->ctr_.params_.label_ ^= SATP_PRF_LABEL_T_HTON(convert_label(kd->role_, dir, label));
+  params->ctr_.params_.seq_ ^= SEQ_NR_T_HTON(seq_nr);
+
+  return 0;
+}
+
+int key_derivation_aesctr_generate(key_derivation_t* kd, key_derivation_dir_t dir, satp_prf_label_t label, seq_nr_t seq_nr, u_int8_t* key, u_int32_t len)
+{
+  if(!kd || !kd->params_ || !kd->master_key_.buf_ || !kd->master_salt_.buf_) {
+    log_printf(ERROR, "key derivation not initialized or no key or salt set");
+    return -1;
+  }
+
+  key_derivation_aesctr_param_t* params = kd->params_;
+
+  if(key_derivation_aesctr_calc_ctr(kd, dir, label, seq_nr)) {
+    log_printf(ERROR, "failed to calculate key derivation CTR");
+    return -1;
+  }
+
+#ifndef USE_SSL_CRYPTO
+  gcry_error_t err = gcry_cipher_reset(params->handle_);
+  if(err) {
+    log_printf(ERROR, "failed to reset key derivation cipher: %s", gcry_strerror(err));
+    return -1;
+  }
+
+  err = gcry_cipher_setctr(params->handle_, params->ctr_.buf_, KD_AESCTR_CTR_LENGTH);
+  if(err) {
+    log_printf(ERROR, "failed to set key derivation CTR: %s", gcry_strerror(err));
+    return -1;
+  }
+
+  memset(key, 0, len);
+  err = gcry_cipher_encrypt(params->handle_, key, len, NULL, 0);
+  if(err) {
+    log_printf(ERROR, "failed to generate key derivation bitstream: %s", gcry_strerror(err));
+    return -1;
+  }
+#else
+  if(KD_AESCTR_CTR_LENGTH != AES_BLOCK_SIZE) {
+    log_printf(ERROR, "failed to set key derivation CTR: size don't fits");
+    return -1;
+  }
+  u_int32_t num = 0;
+  memset(params->ecount_buf_, 0, AES_BLOCK_SIZE);
+  memset(key, 0, len);
+  AES_ctr128_encrypt(key, key, len, &params->aes_key_, params->ctr_.buf_, params->ecount_buf_, &num);
+#endif
+  
+  return 0;
+}
diff --git a/src/key_derivation.h b/src/key_derivation.h
new file mode 100644 (file)
index 0000000..c6212f1
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+ *  uAnytun
+ *
+ *  uAnytun is a tiny implementation of SATP. Unlike Anytun which is a full
+ *  featured implementation uAnytun has no support for multiple connections
+ *  or synchronisation. It is a small single threaded implementation intended
+ *  to act as a client on small platforms.
+ *  The secure anycast tunneling protocol (satp) defines a protocol used
+ *  for communication between any combination of unicast and anycast
+ *  tunnel endpoints.  It has less protocol overhead than IPSec in Tunnel
+ *  mode and allows tunneling of every ETHER TYPE protocol (e.g.
+ *  ethernet, ip, arp ...). satp directly includes cryptography and
+ *  message authentication based on the methodes used by SRTP.  It is
+ *  intended to deliver a generic, scaleable and secure solution for
+ *  tunneling and relaying of packets of any protocol.
+ *  
+ *
+ *  Copyright (C) 2007-2008 Christian Pointner <equinox@anytun.org>
+ *
+ *  This file is part of uAnytun.
+ *
+ *  uAnytun is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 3 as
+ *  published by the Free Software Foundation.
+ *
+ *  uAnytun 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 uAnytun. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _KEY_DERIVATION_H_
+#define _KEY_DERIVATION_H_
+
+#ifndef USE_SSL_CRYPTO
+#include <gcrypt.h>
+#else
+#include <openssl/aes.h>
+#endif
+
+#include "options.h"
+
+#define LABEL_ENC 0
+#define LABEL_AUTH 1
+#define LABEL_SALT 2
+#define LABEL_NIL 3
+
+#define LABEL_LEFT_ENC 0x356A192B
+#define LABEL_RIGHT_ENC 0xDA4B9237
+#define LABEL_LEFT_SALT 0x77DE68DA
+#define LABEL_RIGHT_SALT 0x1B645389
+#define LABEL_LEFT_AUTH 0xAC3478D6
+#define LABEL_RIGHT_AUTH 0xC1DFD96E
+
+enum key_derivation_type_enum { kd_unknown, kd_null, kd_aes_ctr };
+typedef enum key_derivation_type_enum key_derivation_type_t;
+enum key_derivation_dir_enum { kd_inbound, kd_outbound };
+typedef enum key_derivation_dir_enum key_derivation_dir_t;
+
+struct key_derivation_struct {
+  key_derivation_type_t type_;
+  u_int16_t key_length_;
+  role_t role_;
+  buffer_t master_key_;
+  buffer_t master_salt_;
+  void* params_;
+};
+typedef struct key_derivation_struct key_derivation_t;
+
+int key_derivation_init(key_derivation_t* kd, const char* type, role_t role, const char* passphrase, u_int8_t* key, u_int32_t key_len, u_int8_t* salt, u_int32_t salt_len);
+#ifndef NO_PASSPHRASE
+int key_derivation_generate_master_key(key_derivation_t* kd, const char* passphrase, u_int16_t key_length);
+int key_derivation_generate_master_salt(key_derivation_t* kd, const char* passphrase, u_int16_t salt_length);
+#endif
+void key_derivation_close(key_derivation_t* kd);
+int key_derivation_generate(key_derivation_t* kd, key_derivation_dir_t dir, satp_prf_label_t label, seq_nr_t seq_nr, u_int8_t* key, u_int32_t len);
+satp_prf_label_t convert_label(role_t role, key_derivation_dir_t dir, satp_prf_label_t label);
+
+int key_derivation_null_generate(u_int8_t* key, u_int32_t len);
+
+
+#define KD_AESCTR_DEFAULT_KEY_LENGTH 128
+#define KD_AESCTR_CTR_LENGTH 16
+#define KD_AESCTR_SALT_LENGTH 14
+
+union __attribute__((__packed__)) key_derivation_aesctr_ctr_union {
+  u_int8_t buf_[KD_AESCTR_CTR_LENGTH];
+  struct __attribute__ ((__packed__)) {
+    u_int8_t buf_[KD_AESCTR_SALT_LENGTH];
+    u_int16_t zero_;
+  } salt_;
+  struct __attribute__((__packed__)) {
+    u_int8_t fill_[KD_AESCTR_SALT_LENGTH - sizeof(satp_prf_label_t) - sizeof(seq_nr_t)];
+    satp_prf_label_t label_;
+    seq_nr_t seq_;
+    u_int16_t zero_;
+  } params_;
+};
+typedef union key_derivation_aesctr_ctr_union key_derivation_aesctr_ctr_t;
+
+struct key_derivation_aesctr_param_struct {
+#ifndef USE_SSL_CRYPTO
+  gcry_cipher_hd_t handle_;
+#else
+  AES_KEY aes_key_;
+  u_int8_t ecount_buf_[AES_BLOCK_SIZE];
+#endif
+  key_derivation_aesctr_ctr_t ctr_;
+};
+typedef struct key_derivation_aesctr_param_struct key_derivation_aesctr_param_t;
+
+int key_derivation_aesctr_init(key_derivation_t* kd, const char* passphrase);
+void key_derivation_aesctr_close(key_derivation_t* kd);
+int key_derivation_aesctr_calc_ctr(key_derivation_t* kd, key_derivation_dir_t dir, satp_prf_label_t label, seq_nr_t seq_nr);
+int key_derivation_aesctr_generate(key_derivation_t* kd, key_derivation_dir_t dir, satp_prf_label_t label, seq_nr_t seq_nr, u_int8_t* key, u_int32_t len);
+
+#endif
diff --git a/src/linux/tun.c b/src/linux/tun.c
new file mode 100644 (file)
index 0000000..c2187a6
--- /dev/null
@@ -0,0 +1,206 @@
+/*
+ *  uAnytun
+ *
+ *  uAnytun is a tiny implementation of SATP. Unlike Anytun which is a full
+ *  featured implementation uAnytun has no support for multiple connections
+ *  or synchronisation. It is a small single threaded implementation intended
+ *  to act as a client on small platforms.
+ *  The secure anycast tunneling protocol (satp) defines a protocol used
+ *  for communication between any combination of unicast and anycast
+ *  tunnel endpoints.  It has less protocol overhead than IPSec in Tunnel
+ *  mode and allows tunneling of every ETHER TYPE protocol (e.g.
+ *  ethernet, ip, arp ...). satp directly includes cryptography and
+ *  message authentication based on the methodes used by SRTP.  It is
+ *  intended to deliver a generic, scaleable and secure solution for
+ *  tunneling and relaying of packets of any protocol.
+ *  
+ *
+ *  Copyright (C) 2007-2008 Christian Pointner <equinox@anytun.org>
+ *
+ *  This file is part of uAnytun.
+ *
+ *  uAnytun is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 3 as
+ *  published by the Free Software Foundation.
+ *
+ *  uAnytun 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 uAnytun. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdio.h>
+
+#include "datatypes.h"
+
+#include "tun.h"
+
+#include "tun_helper.h"
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/wait.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <arpa/inet.h>
+#include <errno.h>
+#include <net/if.h>
+#include <linux/ip.h>
+#include <linux/if_ether.h>
+#include <linux/if_tun.h>
+#define DEFAULT_DEVICE "/dev/net/tun"
+
+#include "log.h"
+
+int tun_init(tun_device_t* dev, const char* dev_name, const char* dev_type, const char* ifcfg_addr, u_int16_t ifcfg_prefix){
+  if(!dev) 
+    return -1;
+  tun_conf(dev, dev_name, dev_type, ifcfg_addr, ifcfg_prefix, 1400);
+  dev->actual_name_ = NULL;
+
+       dev->fd_ = open(DEFAULT_DEVICE, O_RDWR);
+       if(dev->fd_ < 0) {
+    log_printf(ERROR, "can't open device file (%s): %s", DEFAULT_DEVICE, strerror(errno));
+    tun_close(dev);
+    return -1;
+  }
+
+       struct ifreq ifr;
+       memset(&ifr, 0, sizeof(ifr));
+
+  if(dev->type_ == TYPE_TUN) {
+    ifr.ifr_flags = IFF_TUN;
+    dev->with_pi_ = 1;
+  } 
+  else if(dev->type_ == TYPE_TAP) {
+    ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
+    dev->with_pi_ = 0;
+  } 
+  else {
+    log_printf(ERROR, "unable to recognize type of device (tun or tap)");
+    tun_close(dev);
+    return -1;
+  }
+
+       if(dev_name)
+               strncpy(ifr.ifr_name, dev_name, IFNAMSIZ);
+
+       if(!ioctl(dev->fd_, TUNSETIFF, &ifr)) {
+               dev->actual_name_ = strdup(ifr.ifr_name);
+       } else if(!ioctl(dev->fd_, (('T' << 8) | 202), &ifr)) {
+               dev->actual_name_ = strdup(ifr.ifr_name);
+       } else {
+    log_printf(ERROR, "tun/tap device ioctl failed: %s", strerror(errno));
+    tun_close(dev);
+    return -1;
+  }
+
+  if(!dev->actual_name_) {
+    log_printf(ERROR, "can't open device file: memory error");
+    tun_close(dev);
+    return -2;
+  }
+
+  if(ifcfg_addr)
+    tun_do_ifconfig(dev);
+
+  return 0;
+}
+
+int tun_init_post(tun_device_t* dev)
+{
+// nothing yet
+}
+
+void tun_close(tun_device_t* dev)
+{
+  if(!dev)
+    return;
+
+  if(dev->fd_ > 0)
+    close(dev->fd_);
+
+  if(dev->actual_name_)
+    free(dev->actual_name_);
+
+  if(dev->net_addr_)
+    free(dev->net_addr_);
+
+  if(dev->net_mask_)
+    free(dev->net_mask_);
+}
+
+int tun_read(tun_device_t* dev, u_int8_t* buf, u_int32_t len)
+{
+  if(!dev || dev->fd_ < 0)
+    return -1;
+
+  if(dev->with_pi_)
+  {
+    struct iovec iov[2];
+    struct tun_pi tpi;
+    
+    iov[0].iov_base = &tpi;
+    iov[0].iov_len = sizeof(tpi);
+    iov[1].iov_base = buf;
+    iov[1].iov_len = len;
+    return(tun_fix_return(readv(dev->fd_, iov, 2), sizeof(tpi)));
+  }
+  else
+    return(read(dev->fd_, buf, len));
+}
+
+int tun_write(tun_device_t* dev, u_int8_t* buf, u_int32_t len)
+{
+  if(!dev || dev->fd_ < 0)
+    return -1;
+
+  if(!buf)
+    return 0;
+
+  if(dev->with_pi_)
+  {
+    struct iovec iov[2];
+    struct tun_pi tpi;
+    struct iphdr *hdr = (struct iphdr *)buf;
+    
+    tpi.flags = 0;
+    if(hdr->version == 4)
+      tpi.proto = htons(ETH_P_IP);
+    else
+      tpi.proto = htons(ETH_P_IPV6);
+    
+    iov[0].iov_base = &tpi;
+    iov[0].iov_len = sizeof(tpi);
+    iov[1].iov_base = buf;
+    iov[1].iov_len = len;
+    return(tun_fix_return(writev(dev->fd_, iov, 2), sizeof(tpi)));
+  }
+  else
+    return(write(dev->fd_, buf, len));
+}
+
+void tun_do_ifconfig(tun_device_t* dev)
+{
+  if(!dev || !dev->actual_name_ || !dev->net_addr_ || !dev->net_mask_)
+    return;
+
+  char* command = NULL;
+  asprintf(&command, "/sbin/ifconfig %s %s netmask %s mtu %d", dev->actual_name_, dev->net_addr_, dev->net_mask_, dev->mtu_);
+  if(!command) {
+    log_printf(ERROR, "Execution of ifconfig failed");
+    return;
+  }
+
+  int result = system(command);
+  if(result == -1)
+    log_printf(ERROR, "Execution of ifconfig failed");
+  else
+    log_printf(NOTICE, "ifconfig returned %d", WEXITSTATUS(result));
+
+  free(command);
+}
diff --git a/src/log.c b/src/log.c
new file mode 100644 (file)
index 0000000..847baf7
--- /dev/null
+++ b/src/log.c
@@ -0,0 +1,258 @@
+/*
+ *  uAnytun
+ *
+ *  uAnytun is a tiny implementation of SATP. Unlike Anytun which is a full
+ *  featured implementation uAnytun has no support for multiple connections
+ *  or synchronisation. It is a small single threaded implementation intended
+ *  to act as a client on small platforms.
+ *  The secure anycast tunneling protocol (satp) defines a protocol used
+ *  for communication between any combination of unicast and anycast
+ *  tunnel endpoints.  It has less protocol overhead than IPSec in Tunnel
+ *  mode and allows tunneling of every ETHER TYPE protocol (e.g.
+ *  ethernet, ip, arp ...). satp directly includes cryptography and
+ *  message authentication based on the methodes used by SRTP.  It is
+ *  intended to deliver a generic, scaleable and secure solution for
+ *  tunneling and relaying of packets of any protocol.
+ *  
+ *
+ *  Copyright (C) 2007-2008 Christian Pointner <equinox@anytun.org>
+ *
+ *  This file is part of uAnytun.
+ *
+ *  uAnytun is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 3 as
+ *  published by the Free Software Foundation.
+ *
+ *  uAnytun 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 uAnytun. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "datatypes.h"
+
+#include <string.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#define SYSLOG_NAMES
+#include <syslog.h>
+
+#include "log.h"
+
+log_t stdlog;
+
+#include "log_targets.h"
+
+const char* log_prio_to_string(log_prio_t prio)
+{
+  switch(prio) {
+  case ERROR: return "ERROR";
+  case WARNING: return "WARNING";
+  case NOTICE: return "NOTICE";
+  case INFO: return "INFO";
+  case DEBUG: return "DEBUG";
+  }
+  return "UNKNOWN";
+}
+
+log_target_type_t log_target_parse_type(const char* conf)
+{
+  if(!conf)
+    return TARGET_UNKNOWN;
+
+  if(!strncmp(conf, "syslog", 6)) return TARGET_SYSLOG;
+  if(!strncmp(conf, "file", 4)) return TARGET_FILE;
+  if(!strncmp(conf, "stdout", 6)) return TARGET_STDOUT;
+  if(!strncmp(conf, "stderr", 6)) return TARGET_STDERR;
+
+  return TARGET_UNKNOWN;
+}
+
+int log_targets_target_exists(log_targets_t* targets, log_target_type_t type)
+{
+  if(!targets && !targets->first_)
+    return 0;
+
+  log_target_t* tmp = targets->first_;
+  while(tmp) {
+    if(tmp->type_ == type)
+      return 1;
+    tmp = tmp->next_;
+  }  
+  return 0;
+}
+
+int log_targets_add(log_targets_t* targets, const char* conf)
+{
+  if(!targets)
+    return -1;
+
+  log_target_t* new_target = NULL;
+  int duplicates_allowed = 0;
+  switch(log_target_parse_type(conf)) {
+  case TARGET_SYSLOG: new_target = log_target_syslog_new(); break;
+  case TARGET_FILE: new_target = log_target_file_new(); duplicates_allowed = 1; break;
+  case TARGET_STDOUT: new_target = log_target_stdout_new(); break;
+  case TARGET_STDERR: new_target = log_target_stderr_new(); break;
+  default: return -3;
+  }
+  if(!new_target)
+    return -2;
+
+  if(!duplicates_allowed && log_targets_target_exists(targets, new_target->type_)) {
+    free(new_target);
+    return -4;
+  }
+
+  const char* prioptr = strchr(conf, ':');
+  if(!prioptr || prioptr[1] == 0) {
+    free(new_target);
+    return -1;
+  }
+  prioptr++;
+  if(!isdigit(prioptr[0]) || (prioptr[1] != 0 && prioptr[1] != ',')) {
+    free(new_target);
+    return -1;
+  }
+  new_target->max_prio_ = prioptr[0] - '0';
+  if(new_target->max_prio_ > 0)
+    new_target->enabled_ = 1;
+
+  if(new_target->init != NULL) {
+    const char* confptr = NULL;
+    if(prioptr[1] != 0)
+      confptr = prioptr+2;
+
+    int ret = (*new_target->init)(new_target, confptr);
+    if(ret) {
+      free(new_target);
+      return ret;
+    }
+  }
+
+  if(new_target->open != NULL)
+    (*new_target->open)(new_target);
+
+
+  if(!targets->first_) {
+    targets->first_ = new_target;
+  }
+  else {
+    log_target_t* tmp = targets->first_;
+    while(tmp->next_)
+      tmp = tmp->next_;
+    
+    tmp->next_ = new_target;
+  }
+  return 0;
+}
+
+void log_targets_log(log_targets_t* targets, log_prio_t prio, const char* msg)
+{
+  if(!targets)
+    return;
+
+  log_target_t* tmp = targets->first_;
+  while(tmp) {
+    if(tmp->log != NULL && tmp->enabled_ && tmp->max_prio_ >= prio)
+      (*tmp->log)(tmp, prio, msg);
+
+    tmp = tmp->next_;
+  }
+}
+
+void log_targets_clear(log_targets_t* targets)
+{
+  if(!targets)
+    return;
+
+  while(targets->first_) {
+    log_target_t* tmp = targets->first_;
+    targets->first_ = tmp->next_;
+    if(tmp->close != NULL)
+      (*tmp->close)(tmp);
+    if(tmp->clear != NULL)
+      (*tmp->clear)(tmp);
+    free(tmp);
+  }
+}
+
+
+void log_init()
+{
+  stdlog.max_prio_ = 0;
+  stdlog.targets_.first_ = NULL;
+}
+
+void log_close()
+{
+  log_targets_clear(&stdlog.targets_);
+}
+
+void update_max_prio()
+{
+  log_target_t* tmp = stdlog.targets_.first_;
+  while(tmp) {
+    if(tmp->enabled_ && tmp->max_prio_ > stdlog.max_prio_)
+      stdlog.max_prio_ = tmp->max_prio_;
+
+    tmp = tmp->next_;
+  }
+}
+
+int log_add_target(const char* conf)
+{
+  if(!conf)
+    return -1;
+
+  int ret = log_targets_add(&stdlog.targets_, conf);
+  if(!ret) update_max_prio();
+  return ret;
+}
+
+void log_printf(log_prio_t prio, const char* fmt, ...)
+{
+  if(stdlog.max_prio_ < prio)
+    return;
+
+  static char msg[MSG_LENGTH_MAX];
+  va_list args;
+
+  va_start(args, fmt);
+  vsnprintf(msg, MSG_LENGTH_MAX, fmt, args);
+  va_end(args);
+
+  log_targets_log(&stdlog.targets_, prio, msg);
+}
+
+void log_print_hex_dump(log_prio_t prio, const u_int8_t* buf, u_int32_t len)
+{
+  if(stdlog.max_prio_ < prio)
+    return;
+
+  static char msg[MSG_LENGTH_MAX];
+
+  if(!buf) {
+    snprintf(msg, MSG_LENGTH_MAX, "(NULL)");
+  }
+  else {
+    u_int32_t i;
+    int offset = snprintf(msg, MSG_LENGTH_MAX, "dump(%d): ", len);
+    if(offset < 0)
+      return;
+    u_int8_t* ptr = &msg[offset];
+    
+    for(i=0; i < len; i++) {
+      if(((i+1)*3) >= (MSG_LENGTH_MAX - offset))
+        break;
+      sprintf(ptr, "%02X ", buf[i]);
+      ptr+=3;
+    }
+  }
+  log_targets_log(&stdlog.targets_, prio, msg);
+}
diff --git a/src/log.h b/src/log.h
new file mode 100644 (file)
index 0000000..46ea867
--- /dev/null
+++ b/src/log.h
@@ -0,0 +1,89 @@
+/*
+ *  uAnytun
+ *
+ *  uAnytun is a tiny implementation of SATP. Unlike Anytun which is a full
+ *  featured implementation uAnytun has no support for multiple connections
+ *  or synchronisation. It is a small single threaded implementation intended
+ *  to act as a client on small platforms.
+ *  The secure anycast tunneling protocol (satp) defines a protocol used
+ *  for communication between any combination of unicast and anycast
+ *  tunnel endpoints.  It has less protocol overhead than IPSec in Tunnel
+ *  mode and allows tunneling of every ETHER TYPE protocol (e.g.
+ *  ethernet, ip, arp ...). satp directly includes cryptography and
+ *  message authentication based on the methodes used by SRTP.  It is
+ *  intended to deliver a generic, scaleable and secure solution for
+ *  tunneling and relaying of packets of any protocol.
+ *  
+ *
+ *  Copyright (C) 2007-2008 Christian Pointner <equinox@anytun.org>
+ *
+ *  This file is part of uAnytun.
+ *
+ *  uAnytun is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 3 as
+ *  published by the Free Software Foundation.
+ *
+ *  uAnytun 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 uAnytun. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _LOG_H_
+#define _LOG_H_
+
+#define MSG_LENGTH_MAX 150
+
+enum log_prio_enum { ERROR = 1, WARNING = 2, NOTICE = 3,
+                     INFO = 4, DEBUG = 5 };
+typedef enum log_prio_enum log_prio_t;
+
+const char* log_prio_to_string(log_prio_t prio);
+
+enum log_target_type_enum { TARGET_SYSLOG , TARGET_STDOUT, TARGET_STDERR, TARGET_FILE , TARGET_UNKNOWN };
+typedef enum log_target_type_enum log_target_type_t;
+
+struct log_target_struct {
+  log_target_type_t type_;
+  int (*init)(struct log_target_struct* self, const char* conf);
+  void (*open)(struct log_target_struct* self);
+  void (*log)(struct log_target_struct* self, log_prio_t prio, const char* msg);
+  void (*close)(struct log_target_struct* self);
+  void (*clear)(struct log_target_struct* self);
+  int opened_;
+  int enabled_;
+  log_prio_t max_prio_;
+  void* param_;
+  struct log_target_struct* next_;
+};
+typedef struct log_target_struct log_target_t;
+
+
+struct log_targets_struct {
+  log_target_t* first_;
+};
+typedef struct log_targets_struct log_targets_t;
+
+int log_targets_target_exists(log_targets_t* targets, log_target_type_t type);
+int log_targets_add(log_targets_t* targets, const char* conf);
+void log_targets_log(log_targets_t* targets, log_prio_t prio, const char* msg);
+void log_targets_clear(log_targets_t* targets);
+
+
+struct log_struct {
+  log_prio_t max_prio_;
+  log_targets_t targets_;
+};
+typedef struct log_struct log_t;
+
+void log_init();
+void log_close();
+void update_max_prio();
+int log_add_target(const char* conf);
+void log_printf(log_prio_t prio, const char* fmt, ...);
+void log_print_hex_dump(log_prio_t prio, const u_int8_t* buf, u_int32_t len);
+
+#endif
diff --git a/src/log_targets.h b/src/log_targets.h
new file mode 100644 (file)
index 0000000..0ea8e83
--- /dev/null
@@ -0,0 +1,336 @@
+/*
+ *  uAnytun
+ *
+ *  uAnytun is a tiny implementation of SATP. Unlike Anytun which is a full
+ *  featured implementation uAnytun has no support for multiple connections
+ *  or synchronisation. It is a small single threaded implementation intended
+ *  to act as a client on small platforms.
+ *  The secure anycast tunneling protocol (satp) defines a protocol used
+ *  for communication between any combination of unicast and anycast
+ *  tunnel endpoints.  It has less protocol overhead than IPSec in Tunnel
+ *  mode and allows tunneling of every ETHER TYPE protocol (e.g.
+ *  ethernet, ip, arp ...). satp directly includes cryptography and
+ *  message authentication based on the methodes used by SRTP.  It is
+ *  intended to deliver a generic, scaleable and secure solution for
+ *  tunneling and relaying of packets of any protocol.
+ *  
+ *
+ *  Copyright (C) 2007-2008 Christian Pointner <equinox@anytun.org>
+ *
+ *  This file is part of uAnytun.
+ *
+ *  uAnytun is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 3 as
+ *  published by the Free Software Foundation.
+ *
+ *  uAnytun 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 uAnytun. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+enum syslog_facility_enum { USER = LOG_USER, MAIL = LOG_MAIL,
+                            DAEMON = LOG_DAEMON, AUTH = LOG_AUTH,
+                            SYSLOG = LOG_SYSLOG, LPR = LOG_LPR,
+                            NEWS = LOG_NEWS, UUCP = LOG_UUCP,
+                            CRON = LOG_CRON, AUTHPRIV = LOG_AUTHPRIV,
+                            FTP = LOG_FTP, LOCAL0 = LOG_LOCAL0,
+                            LOCAL1 = LOG_LOCAL1, LOCAL2 = LOG_LOCAL2,
+                            LOCAL3 = LOG_LOCAL3, LOCAL4 = LOG_LOCAL4,
+                            LOCAL5 = LOG_LOCAL5, LOCAL6 = LOG_LOCAL6,
+                            LOCAL7 = LOG_LOCAL7 };
+typedef enum syslog_facility_enum syslog_facility_t;
+
+struct log_target_syslog_param_struct {
+  char* logname_;
+  syslog_facility_t facility_;
+};
+typedef struct log_target_syslog_param_struct log_target_syslog_param_t;
+
+int log_target_syslog_init(log_target_t* self, const char* conf)
+{
+  if(!self || (conf && conf[0] == 0))
+    return -1;
+  
+  self->param_ = malloc(sizeof(log_target_syslog_param_t));
+  if(!self->param_)
+    return -2;
+
+  char* logname;
+  const char* end = NULL;
+  if(!conf)
+    logname = strdup("uanytun");
+  else {
+    end = strchr(conf, ',');
+    if(end) {
+      size_t len = (size_t)(end - conf);
+      if(!len) {
+        free(self->param_);
+        return -1;
+      }  
+      logname = malloc(len+1);
+      if(logname) {
+        strncpy(logname, conf, len);
+        logname[len] = 0;
+      }
+    }
+    else
+      logname = strdup(conf);
+  }
+
+  if(!logname) {
+    free(self->param_);
+    return -2;
+  }
+  ((log_target_syslog_param_t*)(self->param_))->logname_ = logname;
+
+  if(!end) {
+    ((log_target_syslog_param_t*)(self->param_))->facility_ = DAEMON;
+    return 0;
+  }
+  
+  if(end[1] == 0 || end[1] == ',') {
+    free(logname);
+    free(self->param_);
+    return -1;
+  }
+    
+  const char* start = end + 1;
+  end = strchr(start, ',');
+  int i;
+  for(i=0;;++i) {
+    if(facilitynames[i].c_name == NULL) {
+      free(logname);
+      free(self->param_);
+      return -1;
+    }
+
+    if(( end && !strncmp(start, facilitynames[i].c_name, (size_t)(end - start)) && facilitynames[i].c_name[(size_t)(end-start)] == 0) ||
+       (!end && !strcmp(start, facilitynames[i].c_name))) {
+        ((log_target_syslog_param_t*)(self->param_))->facility_ = facilitynames[i].c_val;
+        break;
+    }
+  }
+
+  return 0;
+}
+
+void log_target_syslog_open(log_target_t* self)
+{
+  if(!self || !self->param_)
+    return;
+
+  openlog(((log_target_syslog_param_t*)(self->param_))->logname_, LOG_PID, ((log_target_syslog_param_t*)(self->param_))->facility_);
+  self->opened_ = 1;
+}
+
+void log_target_syslog_log(log_target_t* self, log_prio_t prio, const char* msg)
+{
+  if(!self || !self->param_ || !self->opened_)
+    return;
+
+  syslog((prio + 2) | ((log_target_syslog_param_t*)(self->param_))->facility_, "%s", msg);  
+}
+
+void log_target_syslog_close(log_target_t* self)
+{
+  closelog();
+  self->opened_ = 0;
+}
+
+void log_target_syslog_clear(log_target_t* self)
+{
+  if(!self || !self->param_)
+    return;
+
+  if(((log_target_syslog_param_t*)(self->param_))->logname_)
+    free(((log_target_syslog_param_t*)(self->param_))->logname_);
+
+  free(self->param_);
+}
+
+log_target_t* log_target_syslog_new()
+{
+  log_target_t* tmp = malloc(sizeof(log_target_t));
+  if(!tmp)
+    return NULL;
+
+  tmp->type_ = TARGET_SYSLOG;
+  tmp->init = &log_target_syslog_init;
+  tmp->open = &log_target_syslog_open;
+  tmp->log = &log_target_syslog_log;
+  tmp->close = &log_target_syslog_close;
+  tmp->clear = &log_target_syslog_clear;
+  tmp->opened_ = 0;
+  tmp->enabled_ = 0;
+  tmp->max_prio_ = NOTICE;
+  tmp->param_ = NULL;
+  tmp->next_ = NULL;
+
+  return tmp;
+}
+
+
+struct log_target_file_param_struct {
+  char* logfilename_;
+  FILE* file_;
+};
+typedef struct log_target_file_param_struct log_target_file_param_t;
+
+int log_target_file_init(log_target_t* self, const char* conf)
+{
+  if(!self || (conf && conf[0] == 0))
+    return -1;
+  
+  self->param_ = malloc(sizeof(log_target_file_param_t));
+  if(!self->param_)
+    return -2;
+
+  char* logfilename;
+  if(!conf)
+    logfilename = strdup("uanytun.log");
+  else {
+    const char* end = strchr(conf, ',');
+    if(end) {
+      size_t len = (size_t)(end - conf);
+      if(!len) {
+        free(self->param_);
+        return -1;
+      }  
+      logfilename = malloc(len+1);
+      if(logfilename) {
+        strncpy(logfilename, conf, len);
+        logfilename[len] = 0;
+      }
+    }
+    else
+      logfilename = strdup(conf);
+  }
+
+  if(!logfilename) {
+    free(self->param_);
+    return -2;
+  }
+  ((log_target_file_param_t*)(self->param_))->logfilename_ = logfilename;
+  ((log_target_file_param_t*)(self->param_))->file_ = NULL;
+
+  return 0;
+}
+
+void log_target_file_open(log_target_t* self)
+{
+  if(!self || !self->param_)
+    return;
+
+  ((log_target_file_param_t*)(self->param_))->file_ = fopen(((log_target_file_param_t*)(self->param_))->logfilename_, "w");
+  if(((log_target_file_param_t*)(self->param_))->file_)
+    self->opened_ = 1;
+}
+
+void log_target_file_log(log_target_t* self, log_prio_t prio, const char* msg)
+{
+  if(!self || !self->param_ || !self->opened_)
+    return;
+
+  fprintf(((log_target_file_param_t*)(self->param_))->file_, "%s-%s\n", log_prio_to_string(prio), msg);
+  fflush(((log_target_file_param_t*)(self->param_))->file_);
+}
+
+void log_target_file_close(log_target_t* self)
+{
+  if(!self || !self->param_)
+    return;
+
+  fclose(((log_target_file_param_t*)(self->param_))->file_);
+  self->opened_ = 0;
+}
+
+void log_target_file_clear(log_target_t* self)
+{
+  if(!self || !self->param_)
+    return;
+
+  if(((log_target_file_param_t*)(self->param_))->logfilename_)
+    free(((log_target_file_param_t*)(self->param_))->logfilename_);
+
+  free(self->param_);
+}
+
+
+log_target_t* log_target_file_new()
+{
+  log_target_t* tmp = malloc(sizeof(log_target_t));
+  if(!tmp)
+    return NULL;
+
+  tmp->type_ = TARGET_FILE;
+  tmp->init = &log_target_file_init;
+  tmp->open = &log_target_file_open;
+  tmp->log = &log_target_file_log;
+  tmp->close = &log_target_file_close;
+  tmp->clear = &log_target_file_clear;
+  tmp->opened_ = 0;
+  tmp->enabled_ = 0;
+  tmp->max_prio_ = NOTICE;
+  tmp->param_ = NULL;
+  tmp->next_ = NULL;
+
+  return tmp;
+}
+
+
+void log_target_stdout_log(log_target_t* self, log_prio_t prio, const char* msg)
+{
+  printf("%s-%s\n", log_prio_to_string(prio), msg);
+}
+
+log_target_t* log_target_stdout_new()
+{
+  log_target_t* tmp = malloc(sizeof(log_target_t));
+  if(!tmp)
+    return NULL;
+
+  tmp->type_ = TARGET_STDOUT;
+  tmp->init = NULL;
+  tmp->open = NULL;
+  tmp->log = &log_target_stdout_log;
+  tmp->close = NULL;
+  tmp->clear = NULL;
+  tmp->opened_ = 0;
+  tmp->enabled_ = 0;
+  tmp->max_prio_ = NOTICE;
+  tmp->param_ = NULL;
+  tmp->next_ = NULL;
+
+  return tmp;
+}
+
+
+void log_target_stderr_log(log_target_t* self, log_prio_t prio, const char* msg)
+{
+  fprintf(stderr, "%s-%s\n", log_prio_to_string(prio), msg);
+}
+
+log_target_t* log_target_stderr_new()
+{
+  log_target_t* tmp = malloc(sizeof(log_target_t));
+  if(!tmp)
+    return NULL;
+
+  tmp->type_ = TARGET_STDERR;
+  tmp->init = NULL;
+  tmp->open = NULL;
+  tmp->log = &log_target_stderr_log;
+  tmp->close = NULL;
+  tmp->clear = NULL;
+  tmp->opened_ = 0;
+  tmp->enabled_ = 0;
+  tmp->max_prio_ = NOTICE;
+  tmp->param_ = NULL;
+  tmp->next_ = NULL;
+
+  return tmp;
+}
diff --git a/src/options.c b/src/options.c
new file mode 100644 (file)
index 0000000..2300794
--- /dev/null
@@ -0,0 +1,510 @@
+/*
+ *  uAnytun
+ *
+ *  uAnytun is a tiny implementation of SATP. Unlike Anytun which is a full
+ *  featured implementation uAnytun has no support for multiple connections
+ *  or synchronisation. It is a small single threaded implementation intended
+ *  to act as a client on small platforms.
+ *  The secure anycast tunneling protocol (satp) defines a protocol used
+ *  for communication between any combination of unicast and anycast
+ *  tunnel endpoints.  It has less protocol overhead than IPSec in Tunnel
+ *  mode and allows tunneling of every ETHER TYPE protocol (e.g.
+ *  ethernet, ip, arp ...). satp directly includes cryptography and
+ *  message authentication based on the methodes used by SRTP.  It is
+ *  intended to deliver a generic, scaleable and secure solution for
+ *  tunneling and relaying of packets of any protocol.
+ *  
+ *
+ *  Copyright (C) 2007-2008 Christian Pointner <equinox@anytun.org>
+ *
+ *  This file is part of uAnytun.
+ *
+ *  uAnytun is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 3 as
+ *  published by the Free Software Foundation.
+ *
+ *  uAnytun 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 uAnytun. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "datatypes.h"
+
+#include "options.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "log.h"
+
+#ifndef NO_CRYPT
+#include "auth_algo.h"
+#endif
+
+#define PARSE_BOOL_PARAM(SHORT, LONG, VALUE)             \
+    else if(!strcmp(str,SHORT) || !strcmp(str,LONG))     \
+      VALUE = 1;
+
+#define PARSE_INVERSE_BOOL_PARAM(SHORT, LONG, VALUE)     \
+    else if(!strcmp(str,SHORT) || !strcmp(str,LONG))     \
+      VALUE = 0;
+
+#define PARSE_INT_PARAM(SHORT, LONG, VALUE)              \
+    else if(!strcmp(str,SHORT) || !strcmp(str,LONG))     \
+    {                                                    \
+      if(argc < 1)                                       \
+        return i;                                        \
+      VALUE = atoi(argv[i+1]);                           \
+      argc--;                                            \
+      i++;                                               \
+    }
+
+#define PARSE_STRING_PARAM(SHORT, LONG, VALUE)           \
+    else if(!strcmp(str,SHORT) || !strcmp(str,LONG))     \
+    {                                                    \
+      if(argc < 1 || argv[i+1][0] == '-')                \
+        return i;                                        \
+      if(VALUE) free(VALUE);                             \
+      VALUE = strdup(argv[i+1]);                         \
+      if(!VALUE)                                         \
+        return -2;                                       \
+      argc--;                                            \
+      i++;                                               \
+    }
+
+#define PARSE_STRING_PARAM_SEC(SHORT, LONG, VALUE)       \
+    else if(!strcmp(str,SHORT) || !strcmp(str,LONG))     \
+    {                                                    \
+      if(argc < 1 || argv[i+1][0] == '-')                \
+        return i;                                        \
+      if(VALUE) free(VALUE);                             \
+      VALUE = strdup(argv[i+1]);                         \
+      if(!VALUE)                                         \
+        return -2;                                       \
+      size_t j;                                          \
+      for(j=0; j < strlen(argv[i+1]); ++j)               \
+        argv[i+1][j] = '#';                              \
+      argc--;                                            \
+      i++;                                               \
+    }
+
+#define PARSE_IFCONFIG_PARAM(SHORT, LONG, VALUE)         \
+    else if(!strcmp(str,SHORT) || !strcmp(str,LONG))     \
+    {                                                    \
+      if(argc < 1 || argv[i+1][0] == '-')                \
+        return i;                                        \
+      int ret;                                           \
+      ret = options_parse_ifconfig(argv[i+1], &VALUE);   \
+      if(ret > 0)                                        \
+        return i+1;                                      \
+      if(ret < 0)                                        \
+        return ret;                                      \
+      argc--;                                            \
+      i++;                                               \
+    }
+
+#define PARSE_HEXSTRING_PARAM_SEC(SHORT, LONG, VALUE)    \
+    else if(!strcmp(str,SHORT) || !strcmp(str,LONG))     \
+    {                                                    \
+      if(argc < 1 || argv[i+1][0] == '-')                \
+        return i;                                        \
+      int ret;                                           \
+      ret = options_parse_hex_string(argv[i+1], &VALUE); \
+      if(ret > 0)                                        \
+        return i+1;                                      \
+      else if(ret < 0)                                   \
+        return ret;                                      \
+      size_t j;                                          \
+      for(j=0; j < strlen(argv[i+1]); ++j)               \
+        argv[i+1][j] = '#';                              \
+      argc--;                                            \
+      i++;                                               \
+    }
+
+#define PARSE_STRING_LIST(SHORT, LONG, LIST)             \
+    else if(!strcmp(str,SHORT) || !strcmp(str,LONG))     \
+    {                                                    \
+      if(argc < 1 || argv[i+1][0] == '-')                \
+        return i;                                        \
+      int ret = string_list_add(&LIST, argv[i+1]);       \
+      if(ret == -2)                                      \
+        return ret;                                      \
+      else if(ret)                                       \
+        return i+1;                                      \
+      argc--;                                            \
+      i++;                                               \
+    }
+
+int options_parse_hex_string(const char* hex, buffer_t* buffer)
+{
+  if(!hex || !buffer)
+    return -1;
+
+  u_int32_t hex_len = strlen(hex);
+  if(hex_len%2)
+    return 1;
+
+  if(buffer->buf_) 
+    free(buffer->buf_);
+  
+  buffer->length_ = hex_len/2;
+  buffer->buf_ = malloc(buffer->length_);
+  if(!buffer->buf_) {
+    buffer->length_ = 0;
+    return -2;
+  }
+
+  const char* ptr = hex;
+  int i;
+  for(i=0;i<buffer->length_;++i) {
+    u_int32_t tmp;
+    sscanf(ptr, "%2X", &tmp);
+    buffer->buf_[i] = (u_int8_t)tmp;
+    ptr += 2;
+  }
+
+  return 0;
+}
+
+int options_parse_ifconfig(const char* arg, ifconfig_param_t* ifcfg)
+{
+  char* str = strdup(arg);
+  if(!str)
+    return -2;
+
+  char* ptr = str;
+  for(;*ptr;++ptr) {
+    if(*ptr == '/') {
+      *ptr = 0;
+      ptr++;
+      if(!(*ptr)) {
+        free(str);
+        return 1;
+      }
+      
+      ifcfg->prefix_length_ = atoi(ptr);
+      ifcfg->net_addr_ = strdup(str);
+      free(str);
+
+      if(!ifcfg->net_addr_)
+        return -2;
+
+      return 0;
+    }
+    if(!isdigit(*ptr) && *ptr != '.') {
+      free(str);
+      return 1;
+    }
+  }
+
+  free(str);
+  return 1;
+}
+
+
+int options_parse(options_t* opt, int argc, char* argv[])
+{
+  if(!opt)
+    return -1;
+
+  options_default(opt);
+
+  if(opt->progname_)
+    free(opt->progname_);
+  opt->progname_ = strdup(argv[0]);
+  if(!opt->progname_)
+    return -2;
+
+  argc--;
+
+  char* role = NULL;
+  int i, ipv4_only = 0, ipv6_only = 0;
+  for(i=1; argc > 0; ++i)
+  {
+    char* str = argv[i];
+    argc--;
+
+    if(!strcmp(str,"-h") || !strcmp(str,"--help"))
+      return -1;
+    PARSE_INVERSE_BOOL_PARAM("-D","--nodaemonize", opt->daemonize_)
+    PARSE_STRING_PARAM("-u","--username", opt->username_)
+    PARSE_STRING_PARAM("-g","--groupname", opt->groupname_)
+    PARSE_STRING_PARAM("-C","--chroot", opt->chroot_dir_)
+    PARSE_STRING_PARAM("-P","--write-pid", opt->pid_file_)
+    PARSE_STRING_PARAM("-i","--interface", opt->local_addr_)
+    PARSE_STRING_PARAM("-p","--port", opt->local_port_)
+    PARSE_INT_PARAM("-s","--sender-id", opt->sender_id_)
+    PARSE_STRING_LIST("-L","--log", opt->log_targets_)
+    PARSE_STRING_PARAM("-r","--remote-host", opt->remote_addr_)
+    PARSE_STRING_PARAM("-o","--remote-port", opt->remote_port_)
+    PARSE_BOOL_PARAM("-4","--ipv4-only", ipv4_only)
+    PARSE_BOOL_PARAM("-6","--ipv6-only", ipv6_only)
+    PARSE_STRING_PARAM("-d","--dev", opt->dev_name_)
+    PARSE_STRING_PARAM("-t","--type", opt->dev_type_)
+    PARSE_IFCONFIG_PARAM("-n","--ifconfig", opt->ifconfig_param_)
+    PARSE_STRING_PARAM("-x","--post-up-script", opt->post_up_script_)
+    PARSE_INT_PARAM("-m","--mux", opt->mux_)
+    PARSE_INT_PARAM("-w","--window-size", opt->seq_window_size_)
+#ifndef NO_CRYPT
+    PARSE_STRING_PARAM("-k","--kd-prf", opt->kd_prf_)
+#ifndef NO_PASSPHRASE
+    PARSE_STRING_PARAM_SEC("-E","--passphrase", opt->passphrase_)
+#endif
+    PARSE_STRING_PARAM("-e","--role", role)
+    PARSE_HEXSTRING_PARAM_SEC("-K","--key", opt->key_)
+    PARSE_HEXSTRING_PARAM_SEC("-A","--salt", opt->salt_)
+    PARSE_STRING_PARAM("-c","--cipher", opt->cipher_)
+    PARSE_STRING_PARAM("-a","--auth-algo", opt->auth_algo_)
+    PARSE_INT_PARAM("-b","--auth-tag-length", opt->auth_tag_length_)
+#endif
+    else 
+      return i;
+  }
+  if(ipv4_only && ipv6_only)
+    return -3;
+  if(ipv4_only)
+    opt->resolv_addr_type_ = IPV4_ONLY;
+  if(ipv6_only)
+    opt->resolv_addr_type_ = IPV6_ONLY;
+
+  if(role) {
+    if(!strcmp(role, "alice") || !strcmp(role, "server") || !strcmp(role, "left"))
+      opt->role_ = ROLE_LEFT;
+    else if(!strcmp(role, "bob") || !strcmp(role, "client") || !strcmp(role, "right"))
+      opt->role_ = ROLE_RIGHT;
+    else {
+      free(role);
+      return -4;
+    }
+    free(role);
+  }
+  return 0;
+}
+
+void options_parse_post(options_t* opt)
+{
+  if(!opt)
+    return;
+
+#ifdef NO_V4MAPPED
+  if(opt->resolv_addr_type_ == ANY) {
+    opt->resolv_addr_type_ = IPV4_ONLY;
+    log_printf(WARNING, "No support for V4-mapped Adresses on this platform, defaulting to only use IPv4 addresses");
+  }
+#endif
+
+#ifndef NO_CRYPT
+  if(!strcmp(opt->cipher_, "null") && !strcmp(opt->auth_algo_, "null") && 
+     strcmp(opt->kd_prf_, "null")) {
+    if(opt->kd_prf_)
+      free(opt->kd_prf_);
+    opt->kd_prf_ = strdup("null");
+  }
+  if((strcmp(opt->cipher_, "null") || strcmp(opt->auth_algo_, "null")) && 
+     !strcmp(opt->kd_prf_, "null")) {
+    log_printf(WARNING, "using NULL key derivation with encryption and or authentication enabled!");
+  }
+
+  u_int32_t tag_len_max = auth_algo_get_max_length(opt->auth_algo_);
+  if(!tag_len_max) opt->auth_tag_length_ = 0;
+  else if(tag_len_max < opt->auth_tag_length_) {
+    log_printf(WARNING, "%s auth algo can't generate tags of length %d, using maximum tag length(%d)", opt->auth_algo_, opt->auth_tag_length_, tag_len_max);
+    opt->auth_tag_length_ = tag_len_max;
+  }
+#endif
+
+  if(!(opt->dev_name_) && !(opt->dev_type_))
+    opt->dev_type_ = strdup("tun");
+}
+
+void options_default(options_t* opt)
+{
+  if(!opt)
+    return;
+
+  opt->progname_ = strdup("uanytun");
+  opt->daemonize_ = 1;
+  opt->username_ = NULL;
+  opt->groupname_ = NULL;
+  opt->chroot_dir_ = NULL;
+  opt->pid_file_ = NULL;
+  string_list_init(&opt->log_targets_);
+  opt->local_addr_ = NULL;
+  opt->local_port_ = strdup("4444");
+  opt->sender_id_ = 0;
+  opt->remote_addr_ = NULL;
+  opt->remote_port_ = strdup("4444");
+  opt->resolv_addr_type_ = ANY;
+  opt->dev_name_ = NULL;
+  opt->dev_type_ = NULL;
+  opt->ifconfig_param_.net_addr_ = NULL;
+  opt->ifconfig_param_.prefix_length_ = 0;
+  opt->post_up_script_ = NULL;
+  opt->mux_ = 0;
+  opt->seq_window_size_ = 0;
+#ifndef NO_CRYPT
+  opt->kd_prf_ = strdup("aes-ctr");
+  opt->passphrase_ = NULL;
+  opt->role_ = ROLE_LEFT;
+  opt->cipher_ = strdup("aes-ctr");
+  opt->auth_algo_ = strdup("sha1");
+  opt->auth_tag_length_ = 10;
+#else
+  opt->cipher_ = strdup("null");
+  opt->auth_tag_length_ = 0;
+#endif
+  opt->key_.buf_ = NULL;
+  opt->key_.length_ = 0;
+  opt->salt_.buf_ = NULL;
+  opt->salt_.length_ = 0;
+}
+
+void options_clear(options_t* opt)
+{
+  if(!opt)
+    return;
+
+  if(opt->progname_)
+    free(opt->progname_);
+  if(opt->username_)
+    free(opt->username_);
+  if(opt->groupname_)
+    free(opt->groupname_);
+  if(opt->chroot_dir_)
+    free(opt->chroot_dir_);
+  if(opt->pid_file_)
+    free(opt->pid_file_);
+  string_list_clear(&opt->log_targets_);
+  if(opt->local_addr_)
+    free(opt->local_addr_);
+  if(opt->local_port_)
+    free(opt->local_port_);
+  if(opt->remote_addr_)
+    free(opt->remote_addr_);
+  if(opt->remote_port_)
+    free(opt->remote_port_);
+  if(opt->dev_name_)
+    free(opt->dev_name_);
+  if(opt->dev_type_)
+    free(opt->dev_type_);
+  if(opt->ifconfig_param_.net_addr_)
+    free(opt->ifconfig_param_.net_addr_);
+  if(opt->post_up_script_)
+    free(opt->post_up_script_);
+  if(opt->cipher_)
+    free(opt->cipher_);
+#ifndef NO_CRYPT
+  if(opt->auth_algo_)
+    free(opt->auth_algo_);
+  if(opt->kd_prf_)
+    free(opt->kd_prf_);
+  if(opt->passphrase_)
+    free(opt->passphrase_);
+#endif
+  if(opt->key_.buf_)
+    free(opt->key_.buf_);
+  if(opt->salt_.buf_)
+    free(opt->salt_.buf_);
+}
+
+void options_print_usage()
+{
+  printf("USAGE:\n");
+  printf("uanytun [-h|--help]                         prints this...\n");
+  printf("        [-D|--nodaemonize]                  don't run in background\n");
+  printf("        [-u|--username] <username>          change to this user\n");
+  printf("        [-g|--groupname] <groupname>        change to this group\n");
+  printf("        [-C|--chroot] <path>                chroot to this directory\n");
+  printf("        [-P|--write-pid] <path>             write pid to this file\n");
+  printf("        [-i|--interface] <ip-address>       local ip address to bind to\n");
+  printf("        [-p|--port] <port>                  local port to bind to\n");
+  printf("        [-s|--sender-id ] <sender id>       the sender id to use\n");
+  printf("        [-L|--log] <target>:<level>[,<param1>[,<param2>..]]\n");
+  printf("                                            add a log target, can be invoked several times\n");
+
+  printf("        [-r|--remote-host] <hostname|ip>    remote host\n");
+  printf("        [-o|--remote-port] <port>           remote port\n");
+  printf("        [-4|--ipv4-only]                    always resolv IPv4 addresses\n");
+  printf("        [-6|--ipv6-only]                    always resolv IPv6 addresses\n");
+  printf("        [-d|--dev] <name>                   device name\n");
+  printf("        [-t|--type] <tun|tap>               device type\n");
+
+  printf("        [-n|--ifconfig] <local>/<prefix>    the local address for the tun/tap device and the used prefix length\n");
+  printf("        [-x|--post-up-script] <script>      script gets called after interface is created\n");
+  printf("        [-m|--mux] <mux-id>                 the multiplex id to use\n");
+  printf("        [-w|--window-size] <window size>    seqence number window size\n");
+#ifndef NO_CRYPT
+  printf("        [-k|--kd-prf] <kd-prf type>         key derivation pseudo random function\n");
+#ifndef NO_PASSPHRASE
+  printf("        [-E|--passphrase] <pass phrase>     a passprhase to generate master key and salt from\n");
+#endif
+  printf("        [-K|--key] <master key>             master key to use for encryption\n");
+  printf("        [-A|--salt] <master salt>           master salt to use for encryption\n");
+  printf("        [-e|--role] <role>                  left (alice) or right (bob)");
+  printf("        [-c|--cipher] <cipher type>         payload encryption algorithm\n");
+  printf("        [-a|--auth-algo] <algo type>        message authentication algorithm\n");
+  printf("        [-b|--auth-tag-length] <length>     length of the auth tag\n");
+#endif
+}
+
+void options_print(options_t* opt)
+{
+  if(!opt)
+    return;
+
+  printf("progname: '%s'\n", opt->progname_);
+  printf("daemonize: %d\n", opt->daemonize_);
+  printf("username: '%s'\n", opt->username_);
+  printf("groupname: '%s'\n", opt->groupname_);
+  printf("chroot_dir: '%s'\n", opt->chroot_dir_);
+  printf("pid_file: '%s'\n", opt->pid_file_);
+  printf("log_targets: \n");
+  string_list_print(&opt->log_targets_, "  '", "'\n");
+  printf("local_addr: '%s'\n", opt->local_addr_);
+  printf("local_port: '%s'\n", opt->local_port_);
+  printf("sender_id: %d\n", opt->sender_id_);
+  printf("remote_addr: '%s'\n", opt->remote_addr_);
+  printf("remote_port: '%s'\n", opt->remote_port_);
+  printf("resolv_addr_type: ");
+  switch(opt->resolv_addr_type_) {
+  case ANY: printf("any\n"); break;
+  case IPV4_ONLY: printf("ipv4-only\n"); break;
+  case IPV6_ONLY: printf("ipv6-only\n"); break;
+  default: printf("??\n"); break;
+  }
+  printf("dev_name: '%s'\n", opt->dev_name_);
+  printf("dev_type: '%s'\n", opt->dev_type_);
+  printf("ifconfig_net_addr: '%s'\n", opt->ifconfig_param_.net_addr_);
+  printf("ifconfig_prefix_length: %d\n", opt->ifconfig_param_.prefix_length_);
+  printf("post_up_script: '%s'\n", opt->post_up_script_);
+  printf("mux: %d\n", opt->mux_);
+  printf("seq_window_size: %d\n", opt->seq_window_size_);
+  printf("cipher: '%s'\n", opt->cipher_);
+#ifndef NO_CRYPT
+  printf("auth_algo: '%s'\n", opt->auth_algo_);
+  printf("auth_tag_length: %d\n", opt->auth_tag_length_);
+  printf("kd_prf: '%s'\n", opt->kd_prf_);
+  printf("passphrase: '%s'\n", opt->passphrase_);
+  printf("role: ");
+  switch(opt->role_) {
+  case ROLE_LEFT: printf("left\n"); break;
+  case ROLE_RIGHT: printf("right\n"); break;
+  default: printf("??\n"); break;
+  }
+#endif
+
+  u_int32_t i;
+  printf("key_[%d]: '", opt->key_.length_);
+  for(i=0; i<opt->key_.length_; ++i) printf("%02X", opt->key_.buf_[i]);
+  printf("'\n");
+
+  printf("salt_[%d]: '", opt->salt_.length_);
+  for(i=0; i<opt->salt_.length_; ++i) printf("%02X", opt->salt_.buf_[i]);
+  printf("'\n");
+}
diff --git a/src/options.h b/src/options.h
new file mode 100644 (file)
index 0000000..0f73a0b
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ *  uAnytun
+ *
+ *  uAnytun is a tiny implementation of SATP. Unlike Anytun which is a full
+ *  featured implementation uAnytun has no support for multiple connections
+ *  or synchronisation. It is a small single threaded implementation intended
+ *  to act as a client on small platforms.
+ *  The secure anycast tunneling protocol (satp) defines a protocol used
+ *  for communication between any combination of unicast and anycast
+ *  tunnel endpoints.  It has less protocol overhead than IPSec in Tunnel
+ *  mode and allows tunneling of every ETHER TYPE protocol (e.g.
+ *  ethernet, ip, arp ...). satp directly includes cryptography and
+ *  message authentication based on the methodes used by SRTP.  It is
+ *  intended to deliver a generic, scaleable and secure solution for
+ *  tunneling and relaying of packets of any protocol.
+ *  
+ *
+ *  Copyright (C) 2007-2008 Christian Pointner <equinox@anytun.org>
+ *
+ *  This file is part of uAnytun.
+ *
+ *  uAnytun is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 3 as
+ *  published by the Free Software Foundation.
+ *
+ *  uAnytun 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 uAnytun. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _OPTIONS_H_
+#define _OPTIONS_H_
+
+#include "string_list.h"
+
+struct ifconfig_param_struct {
+  char* net_addr_;
+  u_int16_t prefix_length_;
+};
+typedef struct ifconfig_param_struct ifconfig_param_t;
+
+enum resolv_addr_type_enum { ANY, IPV4_ONLY, IPV6_ONLY };
+typedef enum resolv_addr_type_enum resolv_addr_type_t;
+
+enum role_enum  { ROLE_LEFT, ROLE_RIGHT };
+typedef enum role_enum role_t;
+
+struct options_struct {
+  char* progname_;
+  int daemonize_;
+  char* username_;
+  char* groupname_;
+  char* chroot_dir_;
+  char* pid_file_;
+  string_list_t log_targets_;
+  char* local_addr_;
+  char* local_port_;
+  sender_id_t sender_id_;
+  char* remote_addr_;
+  char* remote_port_;
+  resolv_addr_type_t resolv_addr_type_;
+  char* dev_name_;
+  char* dev_type_;
+  ifconfig_param_t ifconfig_param_;
+  char* post_up_script_;
+  mux_t mux_;
+  window_size_t seq_window_size_;
+  char* cipher_;
+#ifndef NO_CRYPT
+  char* kd_prf_;
+  char* auth_algo_;
+  char* passphrase_;
+  role_t role_;
+#endif
+  u_int32_t auth_tag_length_;
+  buffer_t key_;
+  buffer_t salt_;
+};
+typedef struct options_struct options_t;
+
+int options_parse_hex_string(const char* hex, buffer_t* buffer);
+int options_parse_ifconfig(const char* arg, ifconfig_param_t* ifcfg);
+
+int options_parse(options_t* opt, int argc, char* argv[]);
+void options_parse_post(options_t* opt);
+void options_default(options_t* opt);
+void options_clear(options_t* opt);
+void options_print_usage();
+void options_print(options_t* opt);
+
+#endif
diff --git a/src/plain_packet.c b/src/plain_packet.c
new file mode 100644 (file)
index 0000000..1d7ba2b
--- /dev/null
@@ -0,0 +1,144 @@
+/*
+ *  uAnytun
+ *
+ *  uAnytun is a tiny implementation of SATP. Unlike Anytun which is a full
+ *  featured implementation uAnytun has no support for multiple connections
+ *  or synchronisation. It is a small single threaded implementation intended
+ *  to act as a client on small platforms.
+ *  The secure anycast tunneling protocol (satp) defines a protocol used
+ *  for communication between any combination of unicast and anycast
+ *  tunnel endpoints.  It has less protocol overhead than IPSec in Tunnel
+ *  mode and allows tunneling of every ETHER TYPE protocol (e.g.
+ *  ethernet, ip, arp ...). satp directly includes cryptography and
+ *  message authentication based on the methodes used by SRTP.  It is
+ *  intended to deliver a generic, scaleable and secure solution for
+ *  tunneling and relaying of packets of any protocol.
+ *  
+ *
+ *  Copyright (C) 2007-2008 Christian Pointner <equinox@anytun.org>
+ *
+ *  This file is part of uAnytun.
+ *
+ *  uAnytun is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 3 as
+ *  published by the Free Software Foundation.
+ *
+ *  uAnytun 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 uAnytun. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "datatypes.h"
+
+#include "plain_packet.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+
+void plain_packet_init(plain_packet_t* packet)
+{
+  if(!packet)
+    return;
+
+  memset (packet, 0, sizeof(*packet));
+}
+
+u_int32_t plain_packet_get_header_length()
+{
+  return sizeof(payload_type_t);
+}
+
+u_int8_t* plain_packet_get_packet(plain_packet_t* packet)
+{
+  if(!packet)
+    return NULL;
+
+  return packet->data_.buf_;
+}
+
+u_int32_t plain_packet_get_length(plain_packet_t* packet)
+{
+  if(!packet)
+    return 0;
+
+  return (packet->payload_length_ + sizeof(payload_type_t));
+}
+
+void plain_packet_set_length(plain_packet_t* packet, u_int32_t len)
+{
+  if(!packet)
+    return;
+  
+  if(len > PLAIN_PACKET_SIZE_MAX)
+    len = PLAIN_PACKET_SIZE_MAX - sizeof(payload_type_t);
+  else if(len < sizeof(payload_type_t))
+    len = 0;
+  else
+    len -= sizeof(payload_type_t);
+
+  packet->payload_length_ = len;  
+}
+
+u_int8_t* plain_packet_get_payload(plain_packet_t* packet)
+{
+  if(!packet || !packet->payload_length_)
+    return NULL;
+
+  return (packet->data_.buf_ + sizeof(payload_type_t));
+}
+
+u_int32_t plain_packet_get_payload_length(plain_packet_t* packet)
+{
+  if(!packet)
+    return 0;
+
+  return packet->payload_length_;
+}
+
+void plain_packet_set_payload_length(plain_packet_t* packet, u_int32_t len)
+{
+  if(!packet)
+    return;
+
+  if(len > PLAIN_PACKET_SIZE_MAX || (len + sizeof(payload_type_t)) > PLAIN_PACKET_SIZE_MAX)
+    len = PLAIN_PACKET_SIZE_MAX - sizeof(payload_type_t);
+
+  packet->payload_length_ = len;
+}
+
+payload_type_t plain_packet_get_type(plain_packet_t* packet)
+{
+  if(!packet)
+    return 0;
+
+  return PAYLOAD_TYPE_T_NTOH(packet->data_.payload_type_);
+}
+
+void plain_packet_set_type(plain_packet_t* packet, payload_type_t type)
+{
+  if(!packet)
+    return;
+
+  if(type == PAYLOAD_TYPE_TUN) {
+    if(!packet->payload_length_) {
+      packet->data_.payload_type_ = PAYLOAD_TYPE_T_HTON(PAYLOAD_TYPE_TUN);
+      return;
+    }
+
+    struct ip* hdr = (struct ip*)(packet->data_.buf_ + sizeof(payload_type_t));
+    if(hdr->ip_v == 4)
+      packet->data_.payload_type_ = PAYLOAD_TYPE_T_HTON(PAYLOAD_TYPE_TUN4);
+    else if(hdr->ip_v == 6)
+      packet->data_.payload_type_ = PAYLOAD_TYPE_T_HTON(PAYLOAD_TYPE_TUN6);
+  }
+  else
+    packet->data_.payload_type_ = PAYLOAD_TYPE_T_HTON(type);
+}
diff --git a/src/plain_packet.h b/src/plain_packet.h
new file mode 100644 (file)
index 0000000..ed42893
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ *  uAnytun
+ *
+ *  uAnytun is a tiny implementation of SATP. Unlike Anytun which is a full
+ *  featured implementation uAnytun has no support for multiple connections
+ *  or synchronisation. It is a small single threaded implementation intended
+ *  to act as a client on small platforms.
+ *  The secure anycast tunneling protocol (satp) defines a protocol used
+ *  for communication between any combination of unicast and anycast
+ *  tunnel endpoints.  It has less protocol overhead than IPSec in Tunnel
+ *  mode and allows tunneling of every ETHER TYPE protocol (e.g.
+ *  ethernet, ip, arp ...). satp directly includes cryptography and
+ *  message authentication based on the methodes used by SRTP.  It is
+ *  intended to deliver a generic, scaleable and secure solution for
+ *  tunneling and relaying of packets of any protocol.
+ *  
+ *
+ *  Copyright (C) 2007-2008 Christian Pointner <equinox@anytun.org>
+ *
+ *  This file is part of uAnytun.
+ *
+ *  uAnytun is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 3 as
+ *  published by the Free Software Foundation.
+ *
+ *  uAnytun 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 uAnytun. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _PLAIN_PACKET_H_
+#define _PLAIN_PACKET_H_
+
+#define PLAIN_PACKET_SIZE_MAX 1600
+
+#define PAYLOAD_TYPE_TAP 0x6558
+#define PAYLOAD_TYPE_TUN 0x0000
+#define PAYLOAD_TYPE_TUN4 0x0800
+#define PAYLOAD_TYPE_TUN6 0x86DD 
+#define PAYLOAD_TYPE_UNKNOWN 0xFFFF
+
+struct plain_packet_struct {
+  u_int32_t payload_length_;
+  union __attribute__ ((__packed__)) {
+    u_int8_t buf_[PLAIN_PACKET_SIZE_MAX];
+    payload_type_t payload_type_;
+  } data_;
+};
+typedef struct plain_packet_struct plain_packet_t;
+
+void plain_packet_init(plain_packet_t* packet);
+
+u_int32_t plain_packet_get_header_length();
+
+u_int8_t* plain_packet_get_packet(plain_packet_t* packet);
+u_int32_t plain_packet_get_length(plain_packet_t* packet);
+void plain_packet_set_length(plain_packet_t* packet, u_int32_t len);
+
+u_int8_t* plain_packet_get_payload(plain_packet_t* packet);
+u_int32_t plain_packet_get_payload_length(plain_packet_t* packet);
+void plain_packet_set_payload_length(plain_packet_t* packet, u_int32_t len);
+
+payload_type_t plain_packet_get_type(plain_packet_t* packet);
+void plain_packet_set_type(plain_packet_t* packet, payload_type_t type);
+
+
+#endif
diff --git a/src/seq_window.c b/src/seq_window.c
new file mode 100644 (file)
index 0000000..6c49d2f
--- /dev/null
@@ -0,0 +1,218 @@
+/*
+ *  uAnytun
+ *
+ *  uAnytun is a tiny implementation of SATP. Unlike Anytun which is a full
+ *  featured implementation uAnytun has no support for multiple connections
+ *  or synchronisation. It is a small single threaded implementation intended
+ *  to act as a client on small platforms.
+ *  The secure anycast tunneling protocol (satp) defines a protocol used
+ *  for communication between any combination of unicast and anycast
+ *  tunnel endpoints.  It has less protocol overhead than IPSec in Tunnel
+ *  mode and allows tunneling of every ETHER TYPE protocol (e.g.
+ *  ethernet, ip, arp ...). satp directly includes cryptography and
+ *  message authentication based on the methodes used by SRTP.  It is
+ *  intended to deliver a generic, scaleable and secure solution for
+ *  tunneling and relaying of packets of any protocol.
+ *  
+ *
+ *  Copyright (C) 2007-2008 Christian Pointner <equinox@anytun.org>
+ *
+ *  This file is part of uAnytun.
+ *
+ *  uAnytun is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 3 as
+ *  published by the Free Software Foundation.
+ *
+ *  uAnytun 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 uAnytun. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "datatypes.h"
+
+#include "seq_window.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <stdio.h>
+
+int seq_win_init(seq_win_t* win, window_size_t size)
+{
+  if(!win)
+    return -1;
+
+  win->size_ = size;
+  win->first_ = NULL;
+
+  return 0;
+}
+
+void seq_win_clear(seq_win_t* win)
+{
+  if(!win)
+    return;
+
+  seq_win_element_t* ptr = win->first_;
+  while(ptr) {
+    seq_win_element_t* to_free = ptr;
+    ptr = ptr->next_;
+    if(to_free->window_)
+      free(to_free->window_);
+
+    free(to_free);
+  }
+}
+
+seq_win_element_t* seq_win_new_element(sender_id_t sender_id, seq_nr_t max, window_size_t size)
+{
+  if(!size)
+    return NULL;
+
+  seq_win_element_t* e = malloc(sizeof(seq_win_element_t));
+  if(!e)
+    return NULL;
+
+  e->sender_id_ = sender_id;
+  e->max_ = max;
+  e->pos_ = 0;
+  e->window_ = malloc(sizeof(seq_nr_t)*size);
+  if(!e->window_) {
+    free(e);
+    return NULL;
+  }
+  memset(e->window_, 0, size);
+  e->window_[e->pos_] = 1;
+  e->next_ = NULL;
+
+  return e;
+}
+
+int seq_win_check_and_add(seq_win_t* win, sender_id_t sender_id, seq_nr_t seq_nr)
+{
+  if(!win)
+    return -1;
+
+  if(!win->size_)
+    return 0;
+
+  seq_win_element_t* ptr = win->first_;
+  while(ptr) {
+    if(ptr->sender_id_ == sender_id) {
+
+      int shifted = 0;
+      if(ptr->max_ < win->size_) {
+        ptr->max_ += SEQ_NR_MAX/2;
+        seq_nr += SEQ_NR_MAX/2;
+        shifted = 1;
+      }
+      else if(ptr->max_ > (SEQ_NR_MAX - win->size_)) {
+        ptr->max_ -= SEQ_NR_MAX/2;
+        seq_nr -= SEQ_NR_MAX/2;
+        shifted = 2;
+      }
+
+      seq_nr_t min = ptr->max_ - win->size_ + 1;
+      if(seq_nr < min || seq_nr == ptr->max_) {
+        if(shifted == 1)
+          ptr->max_ -= SEQ_NR_MAX/2;
+        else if(shifted == 2)
+          ptr->max_ += SEQ_NR_MAX/2;
+        return 1;
+      }
+
+      if(seq_nr > ptr->max_) {
+        seq_nr_t diff = seq_nr - ptr->max_;
+        if(diff >= win->size_)
+          diff = win->size_;
+
+        window_size_t new_pos = ptr->pos_ + diff;
+
+        if(new_pos >= win->size_) {
+          new_pos -= win->size_;
+
+          if(ptr->pos_ < win->size_ - 1)
+            memset(&(ptr->window_[ptr->pos_ + 1]), 0, win->size_ - ptr->pos_ - 1);
+
+          memset(ptr->window_, 0, new_pos);
+        }
+        else {
+          memset(&(ptr->window_[ptr->pos_ + 1]), 0, diff);
+        }
+        ptr->pos_ = new_pos;
+        ptr->window_[ptr->pos_] = 1;
+        ptr->max_ = seq_nr;
+
+        if(shifted == 1)
+          ptr->max_ -= SEQ_NR_MAX/2;
+        else if(shifted == 2)
+          ptr->max_ += SEQ_NR_MAX/2;
+        
+        return 0;
+      }
+      
+      seq_nr_t diff = ptr->max_ - seq_nr;
+      window_size_t pos = diff > ptr->pos_ ? ptr->pos_ + win->size_ : ptr->pos_; 
+      pos -= diff;
+
+      if(shifted == 1)
+        ptr->max_ -= SEQ_NR_MAX/2;
+      else if(shifted == 2)
+        ptr->max_ += SEQ_NR_MAX/2;
+
+      int ret = ptr->window_[pos];
+      ptr->window_[pos] = 1;
+      return ret;
+    }
+    ptr = ptr->next_;
+  }  
+  if(!win->first_) {
+    win->first_ = seq_win_new_element(sender_id, seq_nr, win->size_);
+    if(!win->first_)
+      return -2;
+  }
+  else {
+    ptr = win->first_;
+    while(ptr->next_)
+      ptr = ptr->next_;
+    ptr->next_ = seq_win_new_element(sender_id, seq_nr, win->size_);
+    if(!ptr->next_)
+      return -2;
+  }
+  
+  return 0;
+}
+
+void seq_win_print(seq_win_t* win)
+{
+  printf("Sequence Window:\n");
+
+  if(!win)
+    return;
+
+  seq_win_element_t* ptr = win->first_;
+  while(ptr) {
+    printf(" [%u]: (%u)-", ptr->sender_id_, ptr->max_);
+    window_size_t i = ptr->pos_;
+    while(1) {
+      if(ptr->window_[i])
+        printf("O");
+      else
+        printf(".");
+      
+      if(i)
+        i--;
+      else
+        i = win->size_ - 1;
+
+      if(i == ptr->pos_)
+        break;
+    }
+    printf("\n");
+    ptr = ptr->next_;
+  }
+}
diff --git a/src/seq_window.h b/src/seq_window.h
new file mode 100644 (file)
index 0000000..2191d53
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ *  uAnytun
+ *
+ *  uAnytun is a tiny implementation of SATP. Unlike Anytun which is a full
+ *  featured implementation uAnytun has no support for multiple connections
+ *  or synchronisation. It is a small single threaded implementation intended
+ *  to act as a client on small platforms.
+ *  The secure anycast tunneling protocol (satp) defines a protocol used
+ *  for communication between any combination of unicast and anycast
+ *  tunnel endpoints.  It has less protocol overhead than IPSec in Tunnel
+ *  mode and allows tunneling of every ETHER TYPE protocol (e.g.
+ *  ethernet, ip, arp ...). satp directly includes cryptography and
+ *  message authentication based on the methodes used by SRTP.  It is
+ *  intended to deliver a generic, scaleable and secure solution for
+ *  tunneling and relaying of packets of any protocol.
+ *  
+ *
+ *  Copyright (C) 2007-2008 Christian Pointner <equinox@anytun.org>
+ *
+ *  This file is part of uAnytun.
+ *
+ *  uAnytun is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 3 as
+ *  published by the Free Software Foundation.
+ *
+ *  uAnytun 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 uAnytun. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _SEQ_WINDOW_H_
+#define _SEQ_WINDOW_H_
+
+struct seq_win_element_struct {
+  sender_id_t sender_id_;
+  seq_nr_t max_;
+  window_size_t pos_;
+  u_int8_t* window_;
+  struct seq_win_element_struct* next_;
+};
+typedef struct seq_win_element_struct seq_win_element_t;
+
+struct seq_win_struct {
+  window_size_t size_;
+  seq_win_element_t* first_;
+};
+typedef struct seq_win_struct seq_win_t;
+
+int seq_win_init(seq_win_t* win, window_size_t size);
+void seq_win_clear(seq_win_t* win);
+seq_win_element_t* seq_win_new_element(sender_id_t sender_id, seq_nr_t max, window_size_t size);
+int seq_win_check_and_add(seq_win_t* win, sender_id_t sender_id, seq_nr_t seq_nr);
+
+void seq_win_print(seq_win_t* win);
+
+#endif
diff --git a/src/sig_handler.c b/src/sig_handler.c
new file mode 100644 (file)
index 0000000..6fd4b85
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ *  uAnytun
+ *
+ *  uAnytun is a tiny implementation of SATP. Unlike Anytun which is a full
+ *  featured implementation uAnytun has no support for multiple connections
+ *  or synchronisation. It is a small single threaded implementation intended
+ *  to act as a client on small platforms.
+ *  The secure anycast tunneling protocol (satp) defines a protocol used
+ *  for communication between any combination of unicast and anycast
+ *  tunnel endpoints.  It has less protocol overhead than IPSec in Tunnel
+ *  mode and allows tunneling of every ETHER TYPE protocol (e.g.
+ *  ethernet, ip, arp ...). satp directly includes cryptography and
+ *  message authentication based on the methodes used by SRTP.  It is
+ *  intended to deliver a generic, scaleable and secure solution for
+ *  tunneling and relaying of packets of any protocol.
+ *  
+ *
+ *  Copyright (C) 2007-2008 Christian Pointner <equinox@anytun.org>
+ *
+ *  This file is part of uAnytun.
+ *
+ *  uAnytun is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 3 as
+ *  published by the Free Software Foundation.
+ *
+ *  uAnytun 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 uAnytun. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "datatypes.h"
+
+#include "log.h"
+#include <signal.h>
+#include "sig_handler.h"
+
+volatile sig_atomic_t signal_exit = 0;
+
+void signal_init()
+{
+  signal(SIGINT, handle_signal);
+  signal(SIGQUIT, handle_signal);
+  signal(SIGTERM, handle_signal);
+  signal(SIGHUP, handle_signal);
+  signal(SIGUSR1, handle_signal);
+  signal(SIGUSR2, handle_signal);
+}
+
+void handle_signal(int sig)
+{
+  switch(sig) {
+  case SIGINT: log_printf(NOTICE, "SIG-Int caught, exitting"); signal_exit = 1; break;
+  case SIGQUIT: log_printf(NOTICE, "SIG-Quit caught, exitting"); signal_exit = 1; break;
+  case SIGTERM: log_printf(NOTICE, "SIG-Term caught, exitting"); signal_exit = 1; break;
+  case SIGHUP: log_printf(NOTICE, "SIG-Hup caught"); break;
+  case SIGUSR1: log_printf(NOTICE, "SIG-Usr1 caught"); break;
+  case SIGUSR2: log_printf(NOTICE, "SIG-Usr2 caught"); break;
+  default: log_printf(NOTICE, "Signal %d caught, ignoring", sig); break;
+  }
+}
diff --git a/src/sig_handler.h b/src/sig_handler.h
new file mode 100644 (file)
index 0000000..a7779be
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ *  uAnytun
+ *
+ *  uAnytun is a tiny implementation of SATP. Unlike Anytun which is a full
+ *  featured implementation uAnytun has no support for multiple connections
+ *  or synchronisation. It is a small single threaded implementation intended
+ *  to act as a client on small platforms.
+ *  The secure anycast tunneling protocol (satp) defines a protocol used
+ *  for communication between any combination of unicast and anycast
+ *  tunnel endpoints.  It has less protocol overhead than IPSec in Tunnel
+ *  mode and allows tunneling of every ETHER TYPE protocol (e.g.
+ *  ethernet, ip, arp ...). satp directly includes cryptography and
+ *  message authentication based on the methodes used by SRTP.  It is
+ *  intended to deliver a generic, scaleable and secure solution for
+ *  tunneling and relaying of packets of any protocol.
+ *  
+ *
+ *  Copyright (C) 2007-2008 Christian Pointner <equinox@anytun.org>
+ *
+ *  This file is part of uAnytun.
+ *
+ *  uAnytun is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 3 as
+ *  published by the Free Software Foundation.
+ *
+ *  uAnytun 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 uAnytun. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _SIG_HANDLER_H_
+#define _SIG_HANDLER_H_
+
+#include <signal.h>
+
+extern volatile sig_atomic_t signal_exit;
+
+void signal_init();
+void handle_signal(int sig);
+
+#endif
diff --git a/src/string_list.c b/src/string_list.c
new file mode 100644 (file)
index 0000000..f23fcdc
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ *  uAnytun
+ *
+ *  uAnytun is a tiny implementation of SATP. Unlike Anytun which is a full
+ *  featured implementation uAnytun has no support for multiple connections
+ *  or synchronisation. It is a small single threaded implementation intended
+ *  to act as a client on small platforms.
+ *  The secure anycast tunneling protocol (satp) defines a protocol used
+ *  for communication between any combination of unicast and anycast
+ *  tunnel endpoints.  It has less protocol overhead than IPSec in Tunnel
+ *  mode and allows tunneling of every ETHER TYPE protocol (e.g.
+ *  ethernet, ip, arp ...). satp directly includes cryptography and
+ *  message authentication based on the methodes used by SRTP.  It is
+ *  intended to deliver a generic, scaleable and secure solution for
+ *  tunneling and relaying of packets of any protocol.
+ *  
+ *
+ *  Copyright (C) 2007-2008 Christian Pointner <equinox@anytun.org>
+ *
+ *  This file is part of uAnytun.
+ *
+ *  uAnytun is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 3 as
+ *  published by the Free Software Foundation.
+ *
+ *  uAnytun 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 uAnytun. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "string_list.h"
+
+void string_list_init(string_list_t* list)
+{
+  if(!list)
+    return;
+  
+  list->first_ = NULL;
+}
+
+void string_list_clear(string_list_t* list)
+{
+  if(!list)
+    return;
+
+  while(list->first_) {
+    string_list_element_t* tmp;
+    tmp = list->first_;
+    list->first_ = tmp->next_;
+    if(tmp->string_)
+      free(tmp->string_);
+    free(tmp);
+  }
+}
+
+int string_list_add(string_list_t* list, const char* string)
+{
+  if(!list)
+    return -1;
+
+  if(!list->first_) {
+    list->first_ = malloc(sizeof(string_list_element_t));
+    if(!list->first_)
+      return -2;
+
+    list->first_->next_ = 0;
+    list->first_->string_ = strdup(string);
+    if(!list->first_->string_) {
+      free(list->first_);
+      list->first_ = NULL;
+      return -2;
+    }
+  }
+  else {
+    string_list_element_t* tmp = list->first_;
+    while(tmp->next_)
+      tmp = tmp->next_;
+
+    tmp->next_  = malloc(sizeof(string_list_element_t));
+    if(!tmp->next_)
+      return -2;
+
+    tmp->next_->next_ = 0;
+    tmp->next_->string_ = strdup(string);
+    if(!tmp->next_->string_) {
+      free(list->first_);
+      list->first_ = NULL;
+      return -2;
+    }
+  }
+  return 0;
+}
+
+void string_list_print(string_list_t* list, const char* head, const char* tail)
+{
+  if(!list)
+    return;
+  
+  string_list_element_t* tmp = list->first_;
+  while(tmp) {
+    printf("%s%s%s", head, tmp->string_, tail);
+    tmp = tmp->next_;
+  }
+}
diff --git a/src/string_list.h b/src/string_list.h
new file mode 100644 (file)
index 0000000..fc1f4ac
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ *  uAnytun
+ *
+ *  uAnytun is a tiny implementation of SATP. Unlike Anytun which is a full
+ *  featured implementation uAnytun has no support for multiple connections
+ *  or synchronisation. It is a small single threaded implementation intended
+ *  to act as a client on small platforms.
+ *  The secure anycast tunneling protocol (satp) defines a protocol used
+ *  for communication between any combination of unicast and anycast
+ *  tunnel endpoints.  It has less protocol overhead than IPSec in Tunnel
+ *  mode and allows tunneling of every ETHER TYPE protocol (e.g.
+ *  ethernet, ip, arp ...). satp directly includes cryptography and
+ *  message authentication based on the methodes used by SRTP.  It is
+ *  intended to deliver a generic, scaleable and secure solution for
+ *  tunneling and relaying of packets of any protocol.
+ *  
+ *
+ *  Copyright (C) 2007-2008 Christian Pointner <equinox@anytun.org>
+ *
+ *  This file is part of uAnytun.
+ *
+ *  uAnytun is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 3 as
+ *  published by the Free Software Foundation.
+ *
+ *  uAnytun 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 uAnytun. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _STRING_LIST_H_
+#define _STRING_LIST_H_
+
+struct string_list_element_struct {
+  char* string_;
+  struct string_list_element_struct* next_;
+};
+typedef struct string_list_element_struct string_list_element_t;
+
+struct string_list_struct {
+  string_list_element_t* first_;
+};
+typedef struct string_list_struct string_list_t;
+
+void string_list_init(string_list_t* list);
+void string_list_clear(string_list_t* list);
+int string_list_add(string_list_t* list, const char* string);
+
+void string_list_print(string_list_t* list, const char* head, const char* tail);
+
+#endif
diff --git a/src/sysexec.h b/src/sysexec.h
new file mode 100644 (file)
index 0000000..b724433
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ *  uAnytun
+ *
+ *  uAnytun is a tiny implementation of SATP. Unlike Anytun which is a full
+ *  featured implementation uAnytun has no support for multiple connections
+ *  or synchronisation. It is a small single threaded implementation intended
+ *  to act as a client on small platforms.
+ *  The secure anycast tunneling protocol (satp) defines a protocol used
+ *  for communication between any combination of unicast and anycast
+ *  tunnel endpoints.  It has less protocol overhead than IPSec in Tunnel
+ *  mode and allows tunneling of every ETHER TYPE protocol (e.g.
+ *  ethernet, ip, arp ...). satp directly includes cryptography and
+ *  message authentication based on the methodes used by SRTP.  It is
+ *  intended to deliver a generic, scaleable and secure solution for
+ *  tunneling and relaying of packets of any protocol.
+ *  
+ *
+ *  Copyright (C) 2007-2008 Christian Pointner <equinox@anytun.org>
+ *
+ *  This file is part of uAnytun.
+ *
+ *  uAnytun is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 3 as
+ *  published by the Free Software Foundation.
+ *
+ *  uAnytun 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 uAnytun. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _SYSEXEC_H_
+#define _SYSEXEC_H_
+
+int exec_script(const char* script, const char* ifname)
+{
+  if(!script || !ifname)
+    return -1;
+
+  pid_t pid;
+  pid = fork();
+  if(!pid) {
+    int fd;
+    for (fd=getdtablesize();fd>=0;--fd) // close all file descriptors
+      close(fd);
+
+    fd = open("/dev/null",O_RDWR);        // stdin
+    if(fd == -1)
+      log_printf(WARNING,  "can't open stdin");
+    else {
+      if(dup(fd) == -1)   // stdout
+        log_printf(WARNING,  "can't open stdout");
+      if(dup(fd) == -1)   // stderr
+        log_printf(WARNING,  "can't open stderr");
+    }
+    execl("/bin/sh", "/bin/sh", script, ifname, NULL);
+        // if execl return, an error occurred
+    log_printf(ERROR, "error on executing script: %s", strerror(errno));
+    return -1;
+  }
+  int status = 0;
+  waitpid(pid, &status, 0);
+  if(WIFEXITED(status))
+    log_printf(NOTICE, "script '%s' returned %d", script, WEXITSTATUS(status));  
+  else if(WIFSIGNALED(status))
+    log_printf(NOTICE, "script '%s' terminated after signal %d", script, WTERMSIG(status));
+  else
+    log_printf(ERROR, "executing script: unkown error");
+
+  return status;
+
+}
+
+#endif
diff --git a/src/tun.h b/src/tun.h
new file mode 100644 (file)
index 0000000..6e7c302
--- /dev/null
+++ b/src/tun.h
@@ -0,0 +1,68 @@
+/*
+ *  uAnytun
+ *
+ *  uAnytun is a tiny implementation of SATP. Unlike Anytun which is a full
+ *  featured implementation uAnytun has no support for multiple connections
+ *  or synchronisation. It is a small single threaded implementation intended
+ *  to act as a client on small platforms.
+ *  The secure anycast tunneling protocol (satp) defines a protocol used
+ *  for communication between any combination of unicast and anycast
+ *  tunnel endpoints.  It has less protocol overhead than IPSec in Tunnel
+ *  mode and allows tunneling of every ETHER TYPE protocol (e.g.
+ *  ethernet, ip, arp ...). satp directly includes cryptography and
+ *  message authentication based on the methodes used by SRTP.  It is
+ *  intended to deliver a generic, scaleable and secure solution for
+ *  tunneling and relaying of packets of any protocol.
+ *  
+ *
+ *  Copyright (C) 2007-2008 Christian Pointner <equinox@anytun.org>
+ *
+ *  This file is part of uAnytun.
+ *
+ *  uAnytun is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 3 as
+ *  published by the Free Software Foundation.
+ *
+ *  uAnytun 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 uAnytun. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _TUN_H_
+#define _TUN_H_
+
+#include <stdlib.h>
+
+enum device_type_enum { TYPE_UNDEF, TYPE_TUN, TYPE_TAP };
+typedef enum device_type_enum device_type_t;
+
+struct tun_device_struct {
+  int fd_;
+  unsigned int with_pi_;
+  char* actual_name_;
+  device_type_t type_;
+  u_int16_t mtu_;
+  char* net_addr_;
+  char* net_mask_;
+  u_int16_t prefix_length_;
+};
+typedef struct tun_device_struct tun_device_t;
+
+int tun_init(tun_device_t* dev, const char* dev_name, const char* dev_type, const char* ifcfg_addr, u_int16_t ifcfg_prefix);
+int tun_init_post(tun_device_t* dev);
+void tun_do_ifconfig(tun_device_t* dev);
+void tun_close(tun_device_t* dev);
+  
+int tun_read(tun_device_t* dev, u_int8_t* buf, u_int32_t len);
+int tun_write(tun_device_t* dev, u_int8_t* buf, u_int32_t len);
+
+// in tun_helper.h
+void tun_conf(tun_device_t* dev, const char* dev_name, const char* dev_type, const char* ifcfg_addr, u_int16_t ifcfg_prefix, u_int16_t mtu);
+int tun_fix_return(int ret, size_t pi_length);
+const char* tun_get_type_string(tun_device_t* dev);
+
+#endif
diff --git a/src/tun_helper.h b/src/tun_helper.h
new file mode 100644 (file)
index 0000000..396d902
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+ *  uAnytun
+ *
+ *  uAnytun is a tiny implementation of SATP. Unlike Anytun which is a full
+ *  featured implementation uAnytun has no support for multiple connections
+ *  or synchronisation. It is a small single threaded implementation intended
+ *  to act as a client on small platforms.
+ *  The secure anycast tunneling protocol (satp) defines a protocol used
+ *  for communication between any combination of unicast and anycast
+ *  tunnel endpoints.  It has less protocol overhead than IPSec in Tunnel
+ *  mode and allows tunneling of every ETHER TYPE protocol (e.g.
+ *  ethernet, ip, arp ...). satp directly includes cryptography and
+ *  message authentication based on the methodes used by SRTP.  It is
+ *  intended to deliver a generic, scaleable and secure solution for
+ *  tunneling and relaying of packets of any protocol.
+ *  
+ *
+ *  Copyright (C) 2007-2008 Christian Pointner <equinox@anytun.org>
+ *
+ *  This file is part of uAnytun.
+ *
+ *  uAnytun is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 3 as
+ *  published by the Free Software Foundation.
+ *
+ *  uAnytun 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 uAnytun. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _TUN_HELPER_H_
+#define _TUN_HELPER_H_
+
+#include <string.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+void tun_conf(tun_device_t* dev, const char* dev_name, const char* dev_type, const char* ifcfg_addr, u_int16_t ifcfg_prefix, u_int16_t mtu)
+{
+  if(!dev) return;
+
+  dev->mtu_ = mtu;
+  dev->type_ = TYPE_UNDEF;
+  if(dev_type) {
+    if(!strncmp(dev_type, "tun", 3))
+      dev->type_ = TYPE_TUN;
+    else if (!strncmp(dev_type, "tap", 3))
+      dev->type_ = TYPE_TAP;
+  }
+  else if(dev_name) {
+    if(!strncmp(dev_name, "tun", 3))
+      dev->type_ = TYPE_TUN;
+    else if(!strncmp(dev_name, "tap", 3))
+      dev->type_ = TYPE_TAP;
+  }
+
+  dev->net_addr_ = NULL;
+  dev->net_mask_ = NULL;
+  dev->prefix_length_ = 0;
+  if(ifcfg_addr) {
+    dev->net_addr_ = strdup(ifcfg_addr);
+    dev->prefix_length_ = ifcfg_prefix;
+
+    u_int32_t mask = 0;
+    u_int16_t i = 0;
+    for(i = 0; i < ifcfg_prefix; ++i) {
+      mask = mask >> 1;
+      mask |= 0x80000000L;
+    }
+    struct in_addr addr;
+    addr.s_addr = ntohl(mask);
+    dev->net_mask_ = strdup(inet_ntoa(addr));
+  }
+}
+
+
+int tun_fix_return(int ret, size_t pi_length)
+{
+  if(ret < 0)
+    return ret;
+
+  return ((size_t)ret > pi_length ? (ret - pi_length) : 0);
+}
+
+const char* tun_get_type_string(tun_device_t* dev)
+{
+  if(!dev || dev->fd_ < 0)
+    return "";
+  
+  switch(dev->type_)
+  {
+  case TYPE_UNDEF: return "undef"; break;
+  case TYPE_TUN: return "tun"; break;
+  case TYPE_TAP: return "tap"; break;
+  }
+  return "";
+}
+
+
+
+#endif
diff --git a/src/uanytun.c b/src/uanytun.c
new file mode 100644 (file)
index 0000000..c9c6c44
--- /dev/null
@@ -0,0 +1,478 @@
+/*
+ *  uAnytun
+ *
+ *  uAnytun is a tiny implementation of SATP. Unlike Anytun which is a full
+ *  featured implementation uAnytun has no support for multiple connections
+ *  or synchronisation. It is a small single threaded implementation intended
+ *  to act as a client on small platforms.
+ *  The secure anycast tunneling protocol (satp) defines a protocol used
+ *  for communication between any combination of unicast and anycast
+ *  tunnel endpoints.  It has less protocol overhead than IPSec in Tunnel
+ *  mode and allows tunneling of every ETHER TYPE protocol (e.g.
+ *  ethernet, ip, arp ...). satp directly includes cryptography and
+ *  message authentication based on the methodes used by SRTP.  It is
+ *  intended to deliver a generic, scaleable and secure solution for
+ *  tunneling and relaying of packets of any protocol.
+ *  
+ *
+ *  Copyright (C) 2007-2008 Christian Pointner <equinox@anytun.org>
+ *
+ *  This file is part of uAnytun.
+ *
+ *  uAnytun is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 3 as
+ *  published by the Free Software Foundation.
+ *
+ *  uAnytun 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 uAnytun. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "datatypes.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+#include "log.h"
+#include "sig_handler.h"
+#include "options.h"
+
+#include "tun.h"
+#include "udp.h"
+
+#include "plain_packet.h"
+#include "encrypted_packet.h"
+
+#include "seq_window.h"
+
+#include "cipher.h"
+#ifndef NO_CRYPT
+#include "key_derivation.h"
+#include "auth_algo.h"
+
+#ifndef USE_SSL_CRYPTO
+#include <gcrypt.h>
+#endif
+#endif
+
+
+#include "daemon.h"
+#include "sysexec.h"
+
+#ifndef NO_CRYPT
+#ifndef USE_SSL_CRYPTO
+
+#define MIN_GCRYPT_VERSION "1.2.0"
+
+int init_libgcrypt()
+{
+  if(!gcry_check_version(MIN_GCRYPT_VERSION)) {
+    log_printf(NOTICE, "invalid Version of libgcrypt, should be >= %s", MIN_GCRYPT_VERSION);
+    return -1;
+  }
+
+  gcry_error_t err = gcry_control(GCRYCTL_DISABLE_SECMEM, 0);
+  if(err) {
+    log_printf(ERROR, "failed to disable secure memory: %s", gcry_strerror(err));
+    return -1;
+  }
+
+  err = gcry_control(GCRYCTL_INITIALIZATION_FINISHED);
+  if(err) {
+    log_printf(ERROR, "failed to finish libgcrypt initialization: %s", gcry_strerror(err));
+    return -1;
+  }
+
+  log_printf(NOTICE, "libgcrypt init finished");
+  return 0;
+}
+#endif
+#endif
+
+#ifdef NO_CRYPT
+typedef u_int8_t auth_algo_t;
+#endif
+
+int init_main_loop(options_t* opt, cipher_t* c, auth_algo_t* aa, key_derivation_t* kd, seq_win_t* seq_win)
+{
+  int ret = cipher_init(c, opt->cipher_);
+  if(ret) {
+    log_printf(ERROR, "could not initialize cipher of type %s", opt->cipher_);
+    return ret;
+  }
+  
+#ifndef NO_CRYPT
+  ret = auth_algo_init(aa, opt->auth_algo_);
+  if(ret) {
+    log_printf(ERROR, "could not initialize auth algo of type %s", opt->auth_algo_);
+    cipher_close(c);
+    return ret;
+  }
+
+  ret = key_derivation_init(kd, opt->kd_prf_, opt->role_, opt->passphrase_, opt->key_.buf_, opt->key_.length_, opt->salt_.buf_, opt->salt_.length_);
+  if(ret) {
+    log_printf(ERROR, "could not initialize key derivation of type %s", opt->kd_prf_);
+    cipher_close(c);
+    auth_algo_close(aa);
+    return ret;
+  }
+#endif
+
+  ret = seq_win_init(seq_win, opt->seq_window_size_);
+  if(ret) {
+    printf("could not initialize sequence window");
+    cipher_close(c);
+#ifndef NO_CRYPT
+    auth_algo_close(aa);
+    key_derivation_close(kd);
+#endif
+    return ret;
+  }
+  return 0;
+}
+
+int process_tun_data(tun_device_t* dev, udp_socket_t* sock, options_t* opt, plain_packet_t* plain_packet, encrypted_packet_t* encrypted_packet,
+                     cipher_t* c, auth_algo_t* aa, key_derivation_t* kd, seq_nr_t seq_nr)
+{
+  plain_packet_set_payload_length(plain_packet, -1);
+  encrypted_packet_set_length(encrypted_packet, -1);
+
+  int len = tun_read(dev, plain_packet_get_payload(plain_packet), plain_packet_get_payload_length(plain_packet));
+  if(len == -1) {
+    log_printf(ERROR, "error on reading from device: %s", strerror(errno));
+    return 0;
+  }
+  
+  plain_packet_set_payload_length(plain_packet, len);
+  
+  if(dev->type_ == TYPE_TUN)
+    plain_packet_set_type(plain_packet, PAYLOAD_TYPE_TUN);
+  else if(dev->type_ == TYPE_TAP)
+    plain_packet_set_type(plain_packet, PAYLOAD_TYPE_TAP);    
+  else
+    plain_packet_set_type(plain_packet, PAYLOAD_TYPE_UNKNOWN);
+
+  if(!sock->remote_end_set_)
+    return 0;
+  
+  cipher_encrypt(c, kd, kd_outbound, plain_packet, encrypted_packet, seq_nr, opt->sender_id_, opt->mux_); 
+  
+#ifndef NO_CRYPT
+  auth_algo_generate(aa, kd, kd_outbound, encrypted_packet);
+#endif
+  
+  len = udp_write(sock, encrypted_packet_get_packet(encrypted_packet), encrypted_packet_get_length(encrypted_packet));
+  if(len == -1)
+    log_printf(ERROR, "error on sending udp packet: %s", strerror(errno));
+
+  return 0;
+}
+
+int process_sock_data(tun_device_t* dev, udp_socket_t* sock, options_t* opt, plain_packet_t* plain_packet, encrypted_packet_t* encrypted_packet,
+                      cipher_t* c, auth_algo_t* aa, key_derivation_t* kd, seq_win_t* seq_win)
+{
+  plain_packet_set_payload_length(plain_packet, -1);
+  encrypted_packet_set_length(encrypted_packet, -1);
+
+  udp_endpoint_t remote;
+  memset(&remote, 0, sizeof(udp_endpoint_t));
+  int len = udp_read(sock, encrypted_packet_get_packet(encrypted_packet), encrypted_packet_get_length(encrypted_packet), &remote);
+  if(len == -1) {
+    log_printf(ERROR, "error on receiving udp packet: %s", strerror(errno));
+    return 0;
+  }
+  else if(len < encrypted_packet_get_minimum_length(encrypted_packet)) {
+    log_printf(WARNING, "received packet is to short");
+    return 0;
+  }
+  encrypted_packet_set_length(encrypted_packet, len);
+
+#ifndef NO_CRYPT
+  if(!auth_algo_check_tag(aa, kd, kd_inbound, encrypted_packet)) {
+    log_printf(WARNING, "wrong authentication tag, discarding packet");
+    return 0;
+  }
+#endif
+  
+  if(encrypted_packet_get_mux(encrypted_packet) != opt->mux_) {
+    log_printf(WARNING, "wrong mux value, discarding packet");
+    return 0;
+  }
+  
+  int result = seq_win_check_and_add(seq_win, encrypted_packet_get_sender_id(encrypted_packet), encrypted_packet_get_seq_nr(encrypted_packet));
+  if(result > 0) {
+    log_printf(WARNING, "detected replay attack, discarding packet");
+    return 0;
+  }
+  else if(result < 0) {
+    log_printf(ERROR, "memory error at sequence window");
+    return -2;
+  }
+   
+  if(memcmp(&remote, &(sock->remote_end_), sizeof(remote))) {
+    memcpy(&(sock->remote_end_), &remote, sizeof(remote));
+    sock->remote_end_set_ = 1;
+    char* addrstring = udp_endpoint_to_string(remote);
+    log_printf(NOTICE, "autodetected remote host changed %s", addrstring);
+    free(addrstring);
+  }
+
+  if(encrypted_packet_get_payload_length(encrypted_packet) <= plain_packet_get_header_length()) {
+    log_printf(WARNING, "ignoring packet with zero length payload");
+    return 0;
+  }
+
+  int ret = cipher_decrypt(c, kd, kd_inbound, encrypted_packet, plain_packet); 
+  if(ret) 
+    return ret;
+  len = tun_write(dev, plain_packet_get_payload(plain_packet), plain_packet_get_payload_length(plain_packet));
+  if(len == -1)
+    log_printf(ERROR, "error on writing to device: %s", strerror(errno));
+  
+  return 0;
+}
+
+
+int main_loop(tun_device_t* dev, udp_socket_t* sock, options_t* opt)
+{
+  log_printf(INFO, "entering main loop");
+
+  plain_packet_t plain_packet;
+  plain_packet_init(&plain_packet);
+  encrypted_packet_t encrypted_packet;
+  encrypted_packet_init(&encrypted_packet, opt->auth_tag_length_);
+  seq_nr_t seq_nr = 0;
+  fd_set readfds;
+
+  cipher_t c;
+  auth_algo_t aa;
+  key_derivation_t kd;
+  seq_win_t seq_win;
+
+  int ret = init_main_loop(opt, &c, &aa, &kd, &seq_win);
+  if(ret)
+    return ret;
+
+  signal_init();
+  int return_value = 0;
+  while(!return_value) {
+    FD_ZERO(&readfds);
+    FD_SET(dev->fd_, &readfds);
+    FD_SET(sock->fd_, &readfds);
+    int nfds = dev->fd_ > sock->fd_ ? dev->fd_+1 : sock->fd_+1;
+
+    int ret = select(nfds, &readfds, NULL, NULL, NULL);
+    if(ret == -1 && errno != EINTR) {
+      log_printf(ERROR, "select returned with error: %s", strerror(errno));
+      return_value = -1;
+      break;
+    }
+    if(!ret)
+      continue;
+
+    if(signal_exit) {
+      return_value = 1;
+      break;
+    }
+
+    if(FD_ISSET(dev->fd_, &readfds)) {
+      return_value = process_tun_data(dev, sock, opt, &plain_packet, &encrypted_packet, &c, &aa, &kd, seq_nr);
+      seq_nr++;
+      if(return_value)
+        break;
+    }
+
+    if(FD_ISSET(sock->fd_, &readfds)) {
+      return_value = process_sock_data(dev, sock, opt, &plain_packet, &encrypted_packet, &c, &aa, &kd, &seq_win); 
+      if(return_value)
+        break;
+    }
+  }
+
+  cipher_close(&c);
+#ifndef NO_CRYPT
+  auth_algo_close(&aa);
+  key_derivation_close(&kd);
+#endif
+  seq_win_clear(&seq_win);
+
+  return return_value;
+}
+
+int main(int argc, char* argv[])
+{
+  log_init();
+
+  options_t opt;
+  int ret = options_parse(&opt, argc, argv);
+  if(ret) {
+    if(ret > 0) {
+      fprintf(stderr, "syntax error near: %s\n\n", argv[ret]);
+    }
+    if(ret == -2) {
+      fprintf(stderr, "memory error on options_parse, exitting\n");
+    }
+    if(ret == -3) {
+      fprintf(stderr, "syntax error: -4 and -6 are mutual exclusive\n\n");
+    }
+    if(ret == -4) {
+      fprintf(stderr, "syntax error: unknown role name\n\n");
+    }
+
+    if(ret != -2) 
+      options_print_usage();
+
+    options_clear(&opt);
+    log_close();
+    exit(ret);
+  }
+  string_list_element_t* tmp = opt.log_targets_.first_;
+  if(!tmp) {
+    log_add_target("syslog:3,uanytun,daemon");
+  }
+  else {
+    while(tmp) {
+      ret = log_add_target(tmp->string_);
+      if(ret) {
+        switch(ret) {
+        case -2: fprintf(stderr, "memory error on log_add_target, exitting\n"); break;
+        case -3: fprintf(stderr, "unknown log target: '%s', exitting\n", tmp->string_); break;
+        case -4: fprintf(stderr, "this log target is only allowed once: '%s', exitting\n", tmp->string_); break;
+        default: fprintf(stderr, "syntax error near: '%s', exitting\n", tmp->string_); break;
+        }
+        
+        options_clear(&opt);
+        log_close();
+        exit(ret);
+      }
+      tmp = tmp->next_;
+    }
+  }
+
+  log_printf(NOTICE, "just started...");
+  options_parse_post(&opt);
+
+  priv_info_t priv;
+  if(opt.username_)
+    if(priv_init(&priv, opt.username_, opt.groupname_)) {
+      options_clear(&opt);
+      log_close();
+      exit(-1);
+    }
+
+#ifndef NO_CRYPT
+#ifndef USE_SSL_CRYPTO
+  ret = init_libgcrypt();
+  if(ret) {
+    log_printf(ERROR, "error on libgcrpyt initialization, exitting");
+    options_clear(&opt);
+    log_close();
+    exit(ret);
+  }
+#endif
+#endif
+
+  tun_device_t dev;
+  ret = tun_init(&dev, opt.dev_name_, opt.dev_type_, opt.ifconfig_param_.net_addr_, opt.ifconfig_param_.prefix_length_);
+  if(ret) {
+    log_printf(ERROR, "error on tun_init, exitting");
+    options_clear(&opt);
+    log_close();
+    exit(ret);
+  }
+  log_printf(NOTICE, "dev of type '%s' opened, actual name is '%s'", tun_get_type_string(&dev), dev.actual_name_);
+
+  if(opt.post_up_script_) {
+    log_printf(NOTICE, "executing post-up script '%s'", opt.post_up_script_);
+    int ret = exec_script(opt.post_up_script_, dev.actual_name_);
+  }
+
+
+  udp_socket_t sock;
+  ret = udp_init(&sock, opt.local_addr_, opt.local_port_, opt.resolv_addr_type_);
+  if(ret) {
+    log_printf(ERROR, "error on udp_init, exitting");
+    tun_close(&dev);
+    options_clear(&opt);
+    log_close();
+    exit(ret);
+  }
+  char* local_string = udp_get_local_end_string(&sock);
+  if(local_string) {
+    log_printf(NOTICE, "listening on: %s", local_string);
+    free(local_string);
+  }
+
+
+  if(opt.remote_addr_) {
+    if(!udp_set_remote(&sock, opt.remote_addr_, opt.remote_port_, opt.resolv_addr_type_)) {
+      char* remote_string = udp_get_remote_end_string(&sock);
+      if(remote_string) {
+        log_printf(NOTICE, "set remote end to: %s", remote_string);
+        free(remote_string);
+      }
+    }
+  }
+
+
+  FILE* pid_file = NULL;
+  if(opt.pid_file_) {
+    pid_file = fopen(opt.pid_file_, "w");
+    if(!pid_file) {
+      log_printf(WARNING, "unable to open pid file: %s", strerror(errno));
+    }
+  }
+
+  if(opt.chroot_dir_)
+    if(do_chroot(opt.chroot_dir_)) {
+      tun_close(&dev);
+      udp_close(&sock);
+      options_clear(&opt);
+      log_close();
+      exit(-1);
+    }
+  if(opt.username_)
+    if(priv_drop(&priv)) {
+      tun_close(&dev);
+      udp_close(&sock);
+      options_clear(&opt);
+      log_close();
+      exit(-1);
+    }  
+
+  if(opt.daemonize_) {
+    pid_t oldpid = getpid();
+    daemonize();
+    log_printf(INFO, "running in background now (old pid: %d)", oldpid);
+  }
+
+  if(pid_file) {
+    pid_t pid = getpid();
+    fprintf(pid_file, "%d", pid);
+    fclose(pid_file);
+  }
+
+  ret = main_loop(&dev, &sock, &opt);
+
+  tun_close(&dev);
+  udp_close(&sock);
+  options_clear(&opt);
+
+  if(!ret)
+    log_printf(NOTICE, "normal shutdown");
+  else if(ret < 0)
+    log_printf(NOTICE, "shutdown after error");
+  else
+    log_printf(NOTICE, "shutdown after signal");
+
+  log_close();
+
+  return ret;
+}
diff --git a/src/udp.c b/src/udp.c
new file mode 100644 (file)
index 0000000..96e2e23
--- /dev/null
+++ b/src/udp.c
@@ -0,0 +1,235 @@
+/*
+ *  uAnytun
+ *
+ *  uAnytun is a tiny implementation of SATP. Unlike Anytun which is a full
+ *  featured implementation uAnytun has no support for multiple connections
+ *  or synchronisation. It is a small single threaded implementation intended
+ *  to act as a client on small platforms.
+ *  The secure anycast tunneling protocol (satp) defines a protocol used
+ *  for communication between any combination of unicast and anycast
+ *  tunnel endpoints.  It has less protocol overhead than IPSec in Tunnel
+ *  mode and allows tunneling of every ETHER TYPE protocol (e.g.
+ *  ethernet, ip, arp ...). satp directly includes cryptography and
+ *  message authentication based on the methodes used by SRTP.  It is
+ *  intended to deliver a generic, scaleable and secure solution for
+ *  tunneling and relaying of packets of any protocol.
+ *  
+ *
+ *  Copyright (C) 2007-2008 Christian Pointner <equinox@anytun.org>
+ *
+ *  This file is part of uAnytun.
+ *
+ *  uAnytun is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 3 as
+ *  published by the Free Software Foundation.
+ *
+ *  uAnytun 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 uAnytun. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "datatypes.h"
+
+#include "udp.h"
+
+#include "log.h"
+
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <netdb.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+
+int udp_init(udp_socket_t* sock, const char* local_addr, const char* port, resolv_addr_type_t resolv_type)
+{
+  if(!sock || !port) 
+    return -1;
+  sock->fd_ = 0;
+  memset(&(sock->local_end_), 0, sizeof(sock->local_end_));
+  memset(&(sock->remote_end_), 0, sizeof(sock->local_end_));
+  sock->remote_end_set_ = 0;
+
+  struct addrinfo hints, *res;
+
+  res = NULL;
+  memset (&hints, 0, sizeof (hints));
+  hints.ai_socktype = SOCK_DGRAM;
+  hints.ai_flags |= AI_PASSIVE;
+
+  switch(resolv_type) {
+  case IPV4_ONLY: hints.ai_family = PF_INET; break;
+  case IPV6_ONLY: hints.ai_family = PF_INET6; break;
+  default: hints.ai_family = PF_UNSPEC; break;
+  }
+
+  int errcode = getaddrinfo(local_addr, port, &hints, &res);
+  if (errcode != 0) {
+    log_printf(ERROR, "Error resolving local address (%s:%s): %s", (local_addr) ? local_addr : "*", port, gai_strerror(errcode));
+    udp_close(sock);
+    return -1;
+  }
+
+  if(!res) {
+    udp_close(sock);
+    log_printf(ERROR, "getaddrinfo returned no address for %s:%s", local_addr, port);
+    return -1;
+  }
+
+  memcpy(&(sock->local_end_), res->ai_addr, res->ai_addrlen);
+
+  sock->fd_ = socket(res->ai_family, SOCK_DGRAM, 0);
+  if(sock->fd_ < 0) {
+    log_printf(ERROR, "Error on opening udp socket: %s", strerror(errno));
+    freeaddrinfo(res);
+    udp_close(sock);
+    return -1;
+  }
+
+  errcode = bind(sock->fd_, res->ai_addr, res->ai_addrlen);
+  if(errcode) {
+    log_printf(ERROR, "Error on binding udp socket: %s", strerror(errno));
+    freeaddrinfo(res);
+    udp_close(sock);
+    return -1;
+  }
+  
+/* this doesn't work on linux ?? */
+/* #ifdef NO_V4MAPPED */
+/*   if(res->ai_family == AF_INET6) { */
+/*     log_printf(NOTICE, "disabling V4-Mapped addresses"); */
+/*     int on = 1; */
+/*     if(setsockopt(sock->fd_, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on))) */
+/*       log_printf(ERROR, "Error on setting IPV6_V6ONLY socket option: %s", strerror(errno)); */
+/*   } */
+/* #endif */
+  freeaddrinfo(res);
+
+  return 0;
+}
+
+int udp_set_remote(udp_socket_t* sock, const char* remote_addr, const char* port, resolv_addr_type_t resolv_type)
+{
+  if(!sock || !remote_addr || !port) 
+    return -1;
+
+  struct addrinfo hints, *res;
+
+  res = NULL;
+  memset (&hints, 0, sizeof (hints));
+  hints.ai_socktype = SOCK_DGRAM;
+
+  switch(resolv_type) {
+  case IPV4_ONLY: hints.ai_family = PF_INET; break;
+  case IPV6_ONLY: hints.ai_family = PF_INET6; break;
+  default: hints.ai_family = PF_UNSPEC; break;
+  }
+
+  int errcode = getaddrinfo(remote_addr, port, &hints, &res);
+  if (errcode != 0) {
+    log_printf(ERROR, "Error resolving remote address (%s:%s): %s", (remote_addr) ? remote_addr : "*", port, gai_strerror(errcode));
+    return -1;
+  }
+  if(!res) {
+    log_printf(ERROR, "getaddrinfo returned no address for %s:%s", remote_addr, port);
+    return -1;
+  }
+  memcpy(&(sock->remote_end_), res->ai_addr, res->ai_addrlen);
+  sock->remote_end_set_ = 1;
+  freeaddrinfo(res);
+
+  return 0;
+}
+
+void udp_close(udp_socket_t* sock)
+{
+  if(!sock)
+    return;
+
+  if(sock->fd_ > 0)
+    close(sock->fd_);
+}
+
+char* udp_endpoint_to_string(udp_endpoint_t e)
+{
+  void* ptr;
+  u_int16_t port;
+  size_t addrstr_len = 0;
+  char* addrstr, *ret;
+  char addrport_sep = ':';
+
+  switch (((struct sockaddr *)&e)->sa_family)
+  {
+  case AF_INET:
+    ptr = &((struct sockaddr_in *)&e)->sin_addr;
+    port = ntohs(((struct sockaddr_in *)&e)->sin_port);
+    addrstr_len = INET_ADDRSTRLEN + 1;
+    addrport_sep = ':';
+    break;
+  case AF_INET6:
+    ptr = &((struct sockaddr_in6 *)&e)->sin6_addr;
+    port = ntohs(((struct sockaddr_in6 *)&e)->sin6_port);
+    addrstr_len = INET6_ADDRSTRLEN + 1;
+    addrport_sep = '.';
+    break;
+  default:
+    asprintf(&ret, "unknown address type");
+    return ;
+  }
+  addrstr = malloc(addrstr_len);
+  if(!addrstr)
+    return NULL;
+  inet_ntop (((struct sockaddr *)&e)->sa_family, ptr, addrstr, addrstr_len);
+  asprintf(&ret, "%s%c%d", addrstr, addrport_sep ,port);
+  free(addrstr);
+  return ret;
+}
+
+char* udp_get_local_end_string(udp_socket_t* sock)
+{
+  if(!sock)
+    return NULL;
+
+  return udp_endpoint_to_string(sock->local_end_);
+}
+
+char* udp_get_remote_end_string(udp_socket_t* sock)
+{
+  if(!sock || !sock->remote_end_set_)
+    return NULL;
+
+  return udp_endpoint_to_string(sock->remote_end_);
+}
+int udp_read(udp_socket_t* sock, u_int8_t* buf, u_int32_t len, udp_endpoint_t* remote_end)
+{
+  if(!sock || !remote_end)
+    return -1;
+
+  socklen_t socklen = sizeof(*remote_end);
+  return recvfrom(sock->fd_, buf, len, 0, (struct sockaddr *)remote_end, &socklen);
+}
+
+int udp_write(udp_socket_t* sock, u_int8_t* buf, u_int32_t len)
+{
+  if(!sock || !sock->remote_end_set_)
+    return -1;
+
+  socklen_t socklen = sizeof(sock->remote_end_);
+#ifdef NO_V4MAPPED
+  if((((struct sockaddr *)&sock->local_end_)->sa_family) == AF_INET)
+    socklen = sizeof(struct sockaddr_in);
+  else if ((((struct sockaddr *)&sock->local_end_)->sa_family) == AF_INET6)
+    socklen = sizeof(struct sockaddr_in6);
+#endif
+  return sendto(sock->fd_, buf, len, 0, (struct sockaddr *)&(sock->remote_end_), socklen);;
+}
+
diff --git a/src/udp.h b/src/udp.h
new file mode 100644 (file)
index 0000000..aacdae8
--- /dev/null
+++ b/src/udp.h
@@ -0,0 +1,64 @@
+/*
+ *  uAnytun
+ *
+ *  uAnytun is a tiny implementation of SATP. Unlike Anytun which is a full
+ *  featured implementation uAnytun has no support for multiple connections
+ *  or synchronisation. It is a small single threaded implementation intended
+ *  to act as a client on small platforms.
+ *  The secure anycast tunneling protocol (satp) defines a protocol used
+ *  for communication between any combination of unicast and anycast
+ *  tunnel endpoints.  It has less protocol overhead than IPSec in Tunnel
+ *  mode and allows tunneling of every ETHER TYPE protocol (e.g.
+ *  ethernet, ip, arp ...). satp directly includes cryptography and
+ *  message authentication based on the methodes used by SRTP.  It is
+ *  intended to deliver a generic, scaleable and secure solution for
+ *  tunneling and relaying of packets of any protocol.
+ *  
+ *
+ *  Copyright (C) 2007-2008 Christian Pointner <equinox@anytun.org>
+ *
+ *  This file is part of uAnytun.
+ *
+ *  uAnytun is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 3 as
+ *  published by the Free Software Foundation.
+ *
+ *  uAnytun 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 uAnytun. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _UDP_H_
+#define _UDP_H_
+
+#include "options.h"
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+typedef struct sockaddr_storage udp_endpoint_t;
+
+struct udp_socket_struct {
+  int fd_;
+  udp_endpoint_t local_end_;
+  udp_endpoint_t remote_end_;
+  int remote_end_set_;
+};
+typedef struct udp_socket_struct udp_socket_t;
+
+int udp_init(udp_socket_t* sock, const char* local_addr, const char* port, resolv_addr_type_t resolv_type);
+int udp_set_remote(udp_socket_t* sock, const char* remote_addr, const char* port, resolv_addr_type_t resolv_type);
+void udp_close(udp_socket_t* sock);
+
+char* udp_endpoint_to_string(udp_endpoint_t e);
+char* udp_get_local_end_string(udp_socket_t* sock);
+char* udp_get_remote_end_string(udp_socket_t* sock);
+
+int udp_read(udp_socket_t* sock, u_int8_t* buf, u_int32_t len, udp_endpoint_t* remote_end);
+int udp_write(udp_socket_t* sock, u_int8_t* buf, u_int32_t len);
+
+#endif