initial import of hip_release_ver0_6

git-svn-id: svn://svn.code.sf.net/p/openhip/code/hip/trunk@1 4c5cb64f-9889-4596-9799-84b02dc3effa
This commit is contained in:
Jeff Ahrenholz 2009-06-11 15:29:33 +00:00
commit 36136a6684
127 changed files with 64089 additions and 0 deletions

24
AUTHORS Normal file
View File

@ -0,0 +1,24 @@
The authors thank The Boeing Company and its funding sponsor, the Office
of Naval Research, for donating the initial HIP software to the project
in March, 2005, and subsequent updates.
The original design of this software was inspired by the FreeS/WAN project
(http://www.freeswan.org) and OCALA proxy (http://ocala.cs.berkeley.edu).
This file recognizes the individuals who have contributed to this project.
Original authors:
Jeff Ahrenholz (siliconja@users.sourceforge.net)
- primary author and maintainer for past few years
Tom Henderson (tom_henderson@users.sourceforge.net)
- started the original implementation
Jeff Meegan (jmeegan@users.sourceforge.net)
- OS X support, various bugfixes
Patch contributors:
Vivien Schmitt (vivien.schmitt@gmx.de)
- NAT traversal extensions
Miriam Esteban (miriam.esteban@netlab.nec.de)
- rendezvous extensions
Andrei Gurtov (gurtov@cs.helsinki.fi)
- Hi3 patch

257
INSTALL Normal file
View File

@ -0,0 +1,257 @@
For specific instructions on building HIP in different configurations,
consult the OpenHIP wiki:
http://www.openhip.org/wiki/index.php?title=Installation
For the impatient:
./bootstrap.sh (runs aclocal)
./configure --prefix=`pwd`
make install (will build user-mode binaries in ./sbin/ directory)
Refer to the wiki (http://www.openhip.org/wiki/index.php?title=Configuration)
to take the following next steps:
1) generate host identities and configuration file, via the hitgen program
2) running the HIP daemon
3) testing your installation
================================================
| Generic GNU autotools instructions are below |
================================================
Installation Instructions
*************************
Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005 Free
Software Foundation, Inc.
This file is free documentation; the Free Software Foundation gives
unlimited permission to copy, distribute and modify it.
Basic Installation
==================
These are generic installation instructions.
The `configure' shell script attempts to guess correct values for
various system-dependent variables used during compilation. It uses
those values to create a `Makefile' in each directory of the package.
It may also create one or more `.h' files containing system-dependent
definitions. Finally, it creates a shell script `config.status' that
you can run in the future to recreate the current configuration, and a
file `config.log' containing compiler output (useful mainly for
debugging `configure').
It can also use an optional file (typically called `config.cache'
and enabled with `--cache-file=config.cache' or simply `-C') that saves
the results of its tests to speed up reconfiguring. (Caching is
disabled by default to prevent problems with accidental use of stale
cache files.)
If you need to do unusual things to compile the package, please try
to figure out how `configure' could check whether to do them, and mail
diffs or instructions to the address given in the `README' so they can
be considered for the next release. If you are using the cache, and at
some point `config.cache' contains results you don't want to keep, you
may remove or edit it.
The file `configure.ac' (or `configure.in') is used to create
`configure' by a program called `autoconf'. You only need
`configure.ac' if you want to change it or regenerate `configure' using
a newer version of `autoconf'.
The simplest way to compile this package is:
1. `cd' to the directory containing the package's source code and type
`./configure' to configure the package for your system. If you're
using `csh' on an old version of System V, you might need to type
`sh ./configure' instead to prevent `csh' from trying to execute
`configure' itself.
Running `configure' takes awhile. While running, it prints some
messages telling which features it is checking for.
2. Type `make' to compile the package.
3. Optionally, type `make check' to run any self-tests that come with
the package.
4. Type `make install' to install the programs and any data files and
documentation.
5. You can remove the program binaries and object files from the
source code directory by typing `make clean'. To also remove the
files that `configure' created (so you can compile the package for
a different kind of computer), type `make distclean'. There is
also a `make maintainer-clean' target, but that is intended mainly
for the package's developers. If you use it, you may have to get
all sorts of other programs in order to regenerate files that came
with the distribution.
Compilers and Options
=====================
Some systems require unusual options for compilation or linking that the
`configure' script does not know about. Run `./configure --help' for
details on some of the pertinent environment variables.
You can give `configure' initial values for configuration parameters
by setting variables in the command line or in the environment. Here
is an example:
./configure CC=c89 CFLAGS=-O2 LIBS=-lposix
*Note Defining Variables::, for more details.
Compiling For Multiple Architectures
====================================
You can compile the package for more than one kind of computer at the
same time, by placing the object files for each architecture in their
own directory. To do this, you must use a version of `make' that
supports the `VPATH' variable, such as GNU `make'. `cd' to the
directory where you want the object files and executables to go and run
the `configure' script. `configure' automatically checks for the
source code in the directory that `configure' is in and in `..'.
If you have to use a `make' that does not support the `VPATH'
variable, you have to compile the package for one architecture at a
time in the source code directory. After you have installed the
package for one architecture, use `make distclean' before reconfiguring
for another architecture.
Installation Names
==================
By default, `make install' will install the package's files in
`/usr/local/bin', `/usr/local/man', etc. You can specify an
installation prefix other than `/usr/local' by giving `configure' the
option `--prefix=PREFIX'.
You can specify separate installation prefixes for
architecture-specific files and architecture-independent files. If you
give `configure' the option `--exec-prefix=PREFIX', the package will
use PREFIX as the prefix for installing programs and libraries.
Documentation and other data files will still use the regular prefix.
In addition, if you use an unusual directory layout you can give
options like `--bindir=DIR' to specify different values for particular
kinds of files. Run `configure --help' for a list of the directories
you can set and what kinds of files go in them.
If the package supports it, you can cause programs to be installed
with an extra prefix or suffix on their names by giving `configure' the
option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
Optional Features
=================
Some packages pay attention to `--enable-FEATURE' options to
`configure', where FEATURE indicates an optional part of the package.
They may also pay attention to `--with-PACKAGE' options, where PACKAGE
is something like `gnu-as' or `x' (for the X Window System). The
`README' should mention any `--enable-' and `--with-' options that the
package recognizes.
For packages that use the X Window System, `configure' can usually
find the X include and library files automatically, but if it doesn't,
you can use the `configure' options `--x-includes=DIR' and
`--x-libraries=DIR' to specify their locations.
Specifying the System Type
==========================
There may be some features `configure' cannot figure out automatically,
but needs to determine by the type of machine the package will run on.
Usually, assuming the package is built to be run on the _same_
architectures, `configure' can figure that out, but if it prints a
message saying it cannot guess the machine type, give it the
`--build=TYPE' option. TYPE can either be a short name for the system
type, such as `sun4', or a canonical name which has the form:
CPU-COMPANY-SYSTEM
where SYSTEM can have one of these forms:
OS KERNEL-OS
See the file `config.sub' for the possible values of each field. If
`config.sub' isn't included in this package, then this package doesn't
need to know the machine type.
If you are _building_ compiler tools for cross-compiling, you should
use the `--target=TYPE' option to select the type of system they will
produce code for.
If you want to _use_ a cross compiler, that generates code for a
platform different from the build platform, you should specify the
"host" platform (i.e., that on which the generated programs will
eventually be run) with `--host=TYPE'.
Sharing Defaults
================
If you want to set default values for `configure' scripts to share, you
can create a site shell script called `config.site' that gives default
values for variables like `CC', `cache_file', and `prefix'.
`configure' looks for `PREFIX/share/config.site' if it exists, then
`PREFIX/etc/config.site' if it exists. Or, you can set the
`CONFIG_SITE' environment variable to the location of the site script.
A warning: not all `configure' scripts look for a site script.
Defining Variables
==================
Variables not defined in a site shell script can be set in the
environment passed to `configure'. However, some packages may run
configure again during the build, and the customized values of these
variables may be lost. In order to avoid this problem, you should set
them in the `configure' command line, using `VAR=value'. For example:
./configure CC=/usr/local2/bin/gcc
causes the specified `gcc' to be used as the C compiler (unless it is
overridden in the site shell script). Here is a another example:
/bin/bash ./configure CONFIG_SHELL=/bin/bash
Here the `CONFIG_SHELL=/bin/bash' operand causes subsequent
configuration-related scripts to be executed by `/bin/bash'.
`configure' Invocation
======================
`configure' recognizes the following options to control how it operates.
`--help'
`-h'
Print a summary of the options to `configure', and exit.
`--version'
`-V'
Print the version of Autoconf used to generate the `configure'
script, and exit.
`--cache-file=FILE'
Enable the cache: use and save the results of the tests in FILE,
traditionally `config.cache'. FILE defaults to `/dev/null' to
disable caching.
`--config-cache'
`-C'
Alias for `--cache-file=config.cache'.
`--quiet'
`--silent'
`-q'
Do not print messages saying which checks are being made. To
suppress all normal output, redirect it to `/dev/null' (any error
messages will still be shown).
`--srcdir=DIR'
Look for the package's source code in directory DIR. Usually
`configure' can determine that directory automatically.
`configure' also accepts some other, not widely useful, options. Run
`configure --help' for more details.

339
LICENSE Normal file
View File

@ -0,0 +1,339 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) 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
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. 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.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute 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 and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the 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 a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, 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.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE 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.
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
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<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 2 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, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision 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, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This 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.

23
Makefile.am Normal file
View File

@ -0,0 +1,23 @@
#
# Host Identity Protocol
# Copyright (c) 2006 the Boeing Comapny
#
# 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 2 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.
#
# Makefile.am
#
# Author: Jeff Ahrenholz <jeffrey.m.ahrenholz@boeing.com>
#
#
# the real Makefile.am is located in ./src
SUBDIRS = src docs
TARGETS =

146
Makefile.msvc Normal file
View File

@ -0,0 +1,146 @@
# Host Identity Protocol
# Copyright (C) 2002-05 the Boeing Company
#
# 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 2 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.
#
# win32 Makefile for MSVC++
#
# Author: Jeff Ahrenholz, <jeffrey.m.ahrenholz@boeing.com>
#
CC = cl
LIBS = kernel32.lib user32.lib msvcrt.lib ws2_32.lib advapi32.lib iphlpapi.lib iconv.lib libeay32.lib libxml2.lib
# could also link with msvcrt.lib instead of libcmt.lib, build with /MD instead of /MT
LINK = /NODEFAULTLIB /NOLOGO
# this replaces LIB environment variable, but has problems with quotes:
#/LIBPATH:$(LIB);..\lib
SRC = .\src
EXTINC = .\include
SRCINC = $(SRC)\include
INC = -I$(SRCINC) -I$(EXTINC)
SRCPROTO= protocol
SRCUM = usermode
SRCUTIL = util
SRCW32 = win32
# /MT is for threading /MD for MSVCRT.LIB
# /GZ enable runtime debug checks, /Zi enable debugging information, /MDd debug lib
# /MDd for debug
CFLAGS= /MD /Ox /O2 /Ob2 /W3 /WX /Gs0 /GF /Gy /Zi /Zp1 /nologo -DWIN32_LEAN_AND_MEAN $(INC) -D__UMH__ -D__WIN32__ -DCONFIG_HIP -DSYSCONFDIR="\".\""
OBJS = $(SRC)\$(SRCPROTO)\hip_addr.obj \
$(SRC)\$(SRCPROTO)\hip_cache.obj \
$(SRC)\$(SRCPROTO)\hip_dht.obj \
$(SRC)\$(SRCPROTO)\hip_globals.obj \
$(SRC)\$(SRCPROTO)\hip_input.obj \
$(SRC)\$(SRCPROTO)\hip_ipsec.obj \
$(SRC)\$(SRCPROTO)\hip_keymat.obj \
$(SRC)\$(SRCPROTO)\hip_main.obj \
$(SRC)\$(SRCPROTO)\hip_output.obj \
$(SRC)\$(SRCPROTO)\hip_status.obj \
$(SRC)\$(SRCPROTO)\hip_stun.obj \
$(SRC)\$(SRCPROTO)\hip_stun_udp.obj \
$(SRC)\$(SRCUM)\hip_dns.obj \
$(SRC)\$(SRCUM)\hip_esp.obj \
$(SRC)\$(SRCUM)\hip_nl.obj \
$(SRC)\$(SRCUM)\hip_pfkey.obj \
$(SRC)\$(SRCUM)\hip_sadb.obj \
$(SRC)\$(SRCUM)\hip_status2.obj \
$(SRC)\$(SRCUM)\hip_umh_main.obj \
$(SRC)\$(SRCUM)\libipsec_stub.obj \
$(SRC)\$(SRCUTIL)\hip_util.obj \
$(SRC)\$(SRCUTIL)\hip_xml.obj \
$(SRC)\$(SRCW32)\socketpair.obj \
$(SRC)\$(SRCW32)\hip_service.obj
# names of objects used when linking
# (we can eliminate this if .obj files end up in same dir as source)
OBJNAMES=hip_addr.obj \
hip_cache.obj \
hip_dht.obj \
hip_globals.obj \
hip_input.obj \
hip_ipsec.obj \
hip_keymat.obj \
hip_main.obj \
hip_output.obj \
hip_status.obj \
hip_stun.obj \
hip_stun_udp.obj \
hip_dns.obj \
hip_esp.obj \
hip_nl.obj \
hip_pfkey.obj \
hip_sadb.obj \
hip_status2.obj \
hip_umh_main.obj \
libipsec_stub.obj \
hip_util.obj \
hip_xml.obj \
socketpair.obj \
hip_service.obj
HITGENOBJS = $(SRC)\$(SRCUTIL)\hitgen.obj \
$(SRC)\$(SRCPROTO)\hitgen_globals.obj \
$(SRC)\$(SRCUTIL)\hitgen_util.obj
HITGENOBJNAMES = hitgen.obj hitgen_globals.obj hitgen_util.obj
# default target
all: win
# compile objects for Windows service
win: start_win hitgen hipservice finish
#
# build targets
#
hipservice: $(OBJS) $(SRCINC)\hip\hip_service.h
$(CC) $(OBJNAMES) $(CFLAGS) $(LIBS) /link $(LINK) /OUT:hip.exe
# Hitgen utility
hitgen: $(HITGENOBJS)
$(CC) $(HITGENOBJNAMES) $(CFLAGS) -DHITGEN $(LIBS) /link $(LINK) /OUT:hitgen.exe
# Status helper app
status: $(SRC)\$(SRCUTIL)\usermode-status.c
@echo \>\> Building status app...
$(CC) $(CFLAGS) $(SRC)\$(SRCUTIL)\usermode-status.c /OUT:status.exe
#
# source rules
#
# could have source rules here for each object file if needed
#$(SRC)\$(SRCPROTO)\hip_addr.obj: $(SRCINC)\hip\hip_service.h
#$(SRC)\$(SRCPROTO)\hip_cache.obj: $(SRCINC)\hip\hip_service.h
# special rules to control hitgen flags and obj names
$(SRC)\$(SRCPROTO)\hitgen_globals.obj: $(SRC)\$(SRCPROTO)\hip_globals.c
$(CC) $(CFLAGS) -DHITGEN /Fohitgen_globals.obj /c $(SRC)\$(SRCPROTO)\hip_globals.c
$(SRC)\$(SRCUTIL)\hitgen_util.obj: $(SRC)\$(SRCUTIL)\hip_util.c
$(CC) $(CFLAGS) -DHITGEN /Fohitgen_util.obj /c $(SRC)\$(SRCUTIL)\hip_util.c
#
# utility rules
#
start_win:
@echo Building HIP Windows Service...
finish:
copy /Y hitgen.exe .\bin
copy /Y hip.exe .\bin
@echo done.
clean:
@echo Removing binary files...
del hip.exe hitgen.exe
del hip.exp hip.plg hip.ilk hip.ncb hip.opt hip.pdb hip.lib vc60.pdb
del hitgen.exp hitgen.plg hitgen.ilk hitgen.ncb hitgen.opt hitgen.pdb hitgen.lib
del $(OBJNAMES) $(HITGENOBJNAMES)
@echo done.

15
README Normal file
View File

@ -0,0 +1,15 @@
Host Identity Protocol implementation
-------------------------------------
Version 0.6 (May 28, 2009)
For instructions on how to build and install HIP, please refer to the wiki:
http://www.openhip.org/wiki
Release Notes can be found here:
http://www.openhip.org/wiki/index.php?title=Release_Notes
The documentation for this implementation is maintained mainly on
the wiki, but our previous documentation in HTML format can be found
in the file named doc/hipdoc.html.

18
bootstrap.sh Executable file
View File

@ -0,0 +1,18 @@
#!/bin/sh
if [ -d /usr/local/share/aclocal ]; then
EXTRA_INC="-I /usr/local/share/aclocal"
else
EXTRA_INC=""
fi;
if [ `uname` = Darwin ]; then
echo "Using Mac OS X Makefile."
mv -n src/Makefile.am src/Makefile.orig.am
cp src/Makefile.mac.am src/Makefile.am
fi;
echo "Running aclocal..." && aclocal $EXTRA_INC \
&& echo "Running automake..." && automake --add-missing --copy --foreign \
&& echo "Running autoconf..." && autoconf
echo ""
echo "You are now ready to run \"./configure\"."

46
conf/hip.conf Normal file
View File

@ -0,0 +1,46 @@
<?xml version="1.0" encoding="UTF-8"?>
<hip_configuration>
<cookie_difficulty>10</cookie_difficulty>
<packet_timeout>10</packet_timeout>
<max_retries>5</max_retries>
<sa_lifetime>900</sa_lifetime>
<loc_lifetime>1800</loc_lifetime>
<preferred_hi>default-1024</preferred_hi>
<send_hi_name>yes</send_hi_name>
<dh_group>3</dh_group>
<dh_lifetime>900</dh_lifetime>
<r1_lifetime>300</r1_lifetime>
<failure_timeout>50</failure_timeout>
<msl>5</msl>
<ual>600</ual>
<hip_sa>
<transforms>
<id>1</id>
<id>2</id>
<id>3</id>
<id>4</id>
<id>5</id>
<id>6</id>
</transforms>
</hip_sa>
<esp_sa>
<transforms>
<id>1</id>
<id>2</id>
<id>3</id>
<id>4</id>
<id>5</id>
<id>6</id>
</transforms>
</esp_sa>
<!--<dht_server>192.168.0.2</dht_server>
<dht_server_port>5851</dht_server_port>-->
<!--<dns_server>192.168.0.2</dns_server>-->
<disable_dns_lookups>no</disable_dns_lookups>
<disable_notify>no</disable_notify>
<disable_dns_thread>no</disable_dns_thread>
<enable_broadcast>no</enable_broadcast>
<!--<preferred>192.168.0.1</preferred>-->
<!--<preferred_interface>eth0</preferred_interface>-->
<save_known_identities>yes</save_known_identities>
</hip_configuration>

View File

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<known_host_identities>
<host_identity alg="RSA" alg_id="5" length="128" anon="no" incoming="yes">
<name>hipserver.mct.phantomworks.org-1024</name>
<HIT>2001:14:4dcd:2a09:74a:caee:2a0:ec4a</HIT>
<LSI>1.230.120.200</LSI>
</host_identity>
<host_identity alg="RSA" alg_id="5" length="128" anon="no" incoming="yes">
<name>crossroads.infrahip.net-1024</name>
<addr>193.167.187.134</addr>
<HIT>2001:19:b673:8406:e32d:6754:db0b:cde7</HIT>
<LSI>1.11.205.231</LSI>
</host_identity>
<host_identity alg="RSA" alg_id="5" length="128" anon="no" incoming="yes">
<name>woodstock4.hip4inter.net-1024</name>
<addr>193.234.218.202</addr>
<HIT>2001:15:1522:ed39:3a8f:5ef2:eb5:cc30</HIT>
<LSI>1.181.204.48</LSI>
</host_identity>
</known_host_identities>

241
config.h.in Normal file
View File

@ -0,0 +1,241 @@
/* config.h.in. Generated from configure.ac by autoheader. */
/* Define to 1 if you have the <arpa/inet.h> header file. */
#undef HAVE_ARPA_INET_H
/* Define to 1 if you have the `bzero' function. */
#undef HAVE_BZERO
/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */
#undef HAVE_DOPRNT
/* Define to 1 if you have the <fcntl.h> header file. */
#undef HAVE_FCNTL_H
/* Define to 1 if you have the `fork' function. */
#undef HAVE_FORK
/* Define to 1 if you have the `gethostbyname' function. */
#undef HAVE_GETHOSTBYNAME
/* Define to 1 if you have the `gethostname' function. */
#undef HAVE_GETHOSTNAME
/* Define to 1 if you have the `gettimeofday' function. */
#undef HAVE_GETTIMEOFDAY
/* Define to 1 if you have the `inet_ntoa' function. */
#undef HAVE_INET_NTOA
/* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H
/* Define to 1 if you have the `crypto' library (-lcrypto). */
#undef HAVE_LIBCRYPTO
/* Define to 1 if you have the `ipq' library (-lipq). */
#undef HAVE_LIBIPQ
/* Define to 1 if you have the `ipsec' library (-lipsec). */
#undef HAVE_LIBIPSEC
/* Define to 1 if you have the `opensc' library (-lopensc). */
#undef HAVE_LIBOPENSC
/* Define to 1 if you have the `pthread' library (-lpthread). */
#undef HAVE_LIBPTHREAD
/* Define to 1 if you have the `ssl' library (-lssl). */
#undef HAVE_LIBSSL
/* Define to 1 if your system has a GNU libc compatible `malloc' function, and
to 0 otherwise. */
#undef HAVE_MALLOC
/* Define to 1 if you have the `memmove' function. */
#undef HAVE_MEMMOVE
/* Define to 1 if you have the <memory.h> header file. */
#undef HAVE_MEMORY_H
/* Define to 1 if you have the `memset' function. */
#undef HAVE_MEMSET
/* Define to 1 if you have the <netdb.h> header file. */
#undef HAVE_NETDB_H
/* Define to 1 if you have the <netinet/in.h> header file. */
#undef HAVE_NETINET_IN_H
/* Define to 1 if you have the `pow' function. */
#undef HAVE_POW
/* Define to 1 if you have the `select' function. */
#undef HAVE_SELECT
/* Define to 1 if you have the `socket' function. */
#undef HAVE_SOCKET
/* Define to 1 if you have the <stdint.h> header file. */
#undef HAVE_STDINT_H
/* Define to 1 if you have the <stdlib.h> header file. */
#undef HAVE_STDLIB_H
/* Define to 1 if you have the `strchr' function. */
#undef HAVE_STRCHR
/* Define to 1 if you have the `strerror' function. */
#undef HAVE_STRERROR
/* Define to 1 if you have the <strings.h> header file. */
#undef HAVE_STRINGS_H
/* Define to 1 if you have the <string.h> header file. */
#undef HAVE_STRING_H
/* Define to 1 if you have the `strncasecmp' function. */
#undef HAVE_STRNCASECMP
/* Define to 1 if you have the `strrchr' function. */
#undef HAVE_STRRCHR
/* Define to 1 if you have the `strstr' function. */
#undef HAVE_STRSTR
/* Define to 1 if you have the <sys/ioctl.h> header file. */
#undef HAVE_SYS_IOCTL_H
/* Define to 1 if you have the <sys/select.h> header file. */
#undef HAVE_SYS_SELECT_H
/* Define to 1 if you have the <sys/socket.h> header file. */
#undef HAVE_SYS_SOCKET_H
/* Define to 1 if you have the <sys/stat.h> header file. */
#undef HAVE_SYS_STAT_H
/* Define to 1 if you have the <sys/time.h> header file. */
#undef HAVE_SYS_TIME_H
/* Define to 1 if you have the <sys/types.h> header file. */
#undef HAVE_SYS_TYPES_H
/* Define to 1 if you have <sys/wait.h> that is POSIX.1 compatible. */
#undef HAVE_SYS_WAIT_H
/* Define to 1 if you have the `uname' function. */
#undef HAVE_UNAME
/* Define to 1 if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H
/* Define to 1 if you have the `vfork' function. */
#undef HAVE_VFORK
/* Define to 1 if you have the <vfork.h> header file. */
#undef HAVE_VFORK_H
/* Define to 1 if you have the `vprintf' function. */
#undef HAVE_VPRINTF
/* Define to 1 if `fork' works. */
#undef HAVE_WORKING_FORK
/* Define to 1 if `vfork' works. */
#undef HAVE_WORKING_VFORK
/* Define to 1 if your C compiler doesn't accept -c and -o together. */
#undef NO_MINUS_C_MINUS_O
/* Name of package */
#undef PACKAGE
/* Define to the address where bug reports for this package should be sent. */
#undef PACKAGE_BUGREPORT
/* Define to the full name of this package. */
#undef PACKAGE_NAME
/* Define to the full name and version of this package. */
#undef PACKAGE_STRING
/* Define to the one symbol short name of this package. */
#undef PACKAGE_TARNAME
/* Define to the version of this package. */
#undef PACKAGE_VERSION
/* Define as the return type of signal handlers (`int' or `void'). */
#undef RETSIGTYPE
/* Define to the type of arg 1 for `select'. */
#undef SELECT_TYPE_ARG1
/* Define to the type of args 2, 3 and 4 for `select'. */
#undef SELECT_TYPE_ARG234
/* Define to the type of arg 5 for `select'. */
#undef SELECT_TYPE_ARG5
/* Define to 1 if you have the ANSI C header files. */
#undef STDC_HEADERS
/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
#undef TIME_WITH_SYS_TIME
/* Enable extensions on AIX 3, Interix. */
#ifndef _ALL_SOURCE
# undef _ALL_SOURCE
#endif
/* Enable GNU extensions on systems that have them. */
#ifndef _GNU_SOURCE
# undef _GNU_SOURCE
#endif
/* Enable threading extensions on Solaris. */
#ifndef _POSIX_PTHREAD_SEMANTICS
# undef _POSIX_PTHREAD_SEMANTICS
#endif
/* Enable extensions on HP NonStop. */
#ifndef _TANDEM_SOURCE
# undef _TANDEM_SOURCE
#endif
/* Enable general extensions on Solaris. */
#ifndef __EXTENSIONS__
# undef __EXTENSIONS__
#endif
/* Version number of package */
#undef VERSION
/* Define to 1 if on MINIX. */
#undef _MINIX
/* Define to 2 if the system does not provide POSIX.1 features except with
this defined. */
#undef _POSIX_1_SOURCE
/* Define to 1 if you need to in order for `stat' and other things to work. */
#undef _POSIX_SOURCE
/* Define to empty if `const' does not conform to ANSI C. */
#undef const
/* Define to `__inline__' or `__inline' if that's what the C compiler
calls it, or to nothing if 'inline' is not supported under any name. */
#ifndef __cplusplus
#undef inline
#endif
/* Define to rpl_malloc if the replacement function should be used. */
#undef malloc
/* Define to `int' if <sys/types.h> does not define. */
#undef pid_t
/* Define to `unsigned int' if <sys/types.h> does not define. */
#undef size_t
/* Define as `fork' if `vfork' does not work. */
#undef vfork

142
config/compile Executable file
View File

@ -0,0 +1,142 @@
#! /bin/sh
# Wrapper for compilers which do not understand `-c -o'.
scriptversion=2005-02-03.08
# Copyright (C) 1999, 2000, 2003, 2004, 2005 Free Software Foundation, Inc.
# Written by Tom Tromey <tromey@cygnus.com>.
#
# 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 2, 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, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
# This file is maintained in Automake, please report
# bugs to <bug-automake@gnu.org> or send patches to
# <automake-patches@gnu.org>.
case $1 in
'')
echo "$0: No command. Try \`$0 --help' for more information." 1>&2
exit 1;
;;
-h | --h*)
cat <<\EOF
Usage: compile [--help] [--version] PROGRAM [ARGS]
Wrapper for compilers which do not understand `-c -o'.
Remove `-o dest.o' from ARGS, run PROGRAM with the remaining
arguments, and rename the output as expected.
If you are trying to build a whole package this is not the
right script to run: please start by reading the file `INSTALL'.
Report bugs to <bug-automake@gnu.org>.
EOF
exit $?
;;
-v | --v*)
echo "compile $scriptversion"
exit $?
;;
esac
ofile=
cfile=
eat=
for arg
do
if test -n "$eat"; then
eat=
else
case $1 in
-o)
# configure might choose to run compile as `compile cc -o foo foo.c'.
# So we strip `-o arg' only if arg is an object.
eat=1
case $2 in
*.o | *.obj)
ofile=$2
;;
*)
set x "$@" -o "$2"
shift
;;
esac
;;
*.c)
cfile=$1
set x "$@" "$1"
shift
;;
*)
set x "$@" "$1"
shift
;;
esac
fi
shift
done
if test -z "$ofile" || test -z "$cfile"; then
# If no `-o' option was seen then we might have been invoked from a
# pattern rule where we don't need one. That is ok -- this is a
# normal compilation that the losing compiler can handle. If no
# `.c' file was seen then we are probably linking. That is also
# ok.
exec "$@"
fi
# Name of file we expect compiler to create.
cofile=`echo "$cfile" | sed -e 's|^.*/||' -e 's/\.c$/.o/'`
# Create the lock directory.
# Note: use `[/.-]' here to ensure that we don't use the same name
# that we are using for the .o file. Also, base the name on the expected
# object file name, since that is what matters with a parallel build.
lockdir=`echo "$cofile" | sed -e 's|[/.-]|_|g'`.d
while true; do
if mkdir "$lockdir" >/dev/null 2>&1; then
break
fi
sleep 1
done
# FIXME: race condition here if user kills between mkdir and trap.
trap "rmdir '$lockdir'; exit 1" 1 2 15
# Run the compile.
"$@"
ret=$?
if test -f "$cofile"; then
mv "$cofile" "$ofile"
elif test -f "${cofile}bj"; then
mv "${cofile}bj" "$ofile"
fi
rmdir "$lockdir"
exit $ret
# Local Variables:
# mode: shell-script
# sh-indentation: 2
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-end: "$"
# End:

1459
config/config.guess vendored Executable file

File diff suppressed because it is too large Load Diff

1566
config/config.sub vendored Executable file

File diff suppressed because it is too large Load Diff

529
config/depcomp Executable file
View File

@ -0,0 +1,529 @@
#! /bin/sh
# depcomp - compile a program generating dependencies as side-effects
scriptversion=2005-02-09.22
# Copyright (C) 1999, 2000, 2003, 2004, 2005 Free Software Foundation, Inc.
# 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 2, 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, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
# 02111-1307, USA.
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
# Originally written by Alexandre Oliva <oliva@dcc.unicamp.br>.
case $1 in
'')
echo "$0: No command. Try \`$0 --help' for more information." 1>&2
exit 1;
;;
-h | --h*)
cat <<\EOF
Usage: depcomp [--help] [--version] PROGRAM [ARGS]
Run PROGRAMS ARGS to compile a file, generating dependencies
as side-effects.
Environment variables:
depmode Dependency tracking mode.
source Source file read by `PROGRAMS ARGS'.
object Object file output by `PROGRAMS ARGS'.
DEPDIR directory where to store dependencies.
depfile Dependency file to output.
tmpdepfile Temporary file to use when outputing dependencies.
libtool Whether libtool is used (yes/no).
Report bugs to <bug-automake@gnu.org>.
EOF
exit $?
;;
-v | --v*)
echo "depcomp $scriptversion"
exit $?
;;
esac
if test -z "$depmode" || test -z "$source" || test -z "$object"; then
echo "depcomp: Variables source, object and depmode must be set" 1>&2
exit 1
fi
# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po.
depfile=${depfile-`echo "$object" |
sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`}
tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`}
rm -f "$tmpdepfile"
# Some modes work just like other modes, but use different flags. We
# parameterize here, but still list the modes in the big case below,
# to make depend.m4 easier to write. Note that we *cannot* use a case
# here, because this file can only contain one case statement.
if test "$depmode" = hp; then
# HP compiler uses -M and no extra arg.
gccflag=-M
depmode=gcc
fi
if test "$depmode" = dashXmstdout; then
# This is just like dashmstdout with a different argument.
dashmflag=-xM
depmode=dashmstdout
fi
case "$depmode" in
gcc3)
## gcc 3 implements dependency tracking that does exactly what
## we want. Yay! Note: for some reason libtool 1.4 doesn't like
## it if -MD -MP comes after the -MF stuff. Hmm.
"$@" -MT "$object" -MD -MP -MF "$tmpdepfile"
stat=$?
if test $stat -eq 0; then :
else
rm -f "$tmpdepfile"
exit $stat
fi
mv "$tmpdepfile" "$depfile"
;;
gcc)
## There are various ways to get dependency output from gcc. Here's
## why we pick this rather obscure method:
## - Don't want to use -MD because we'd like the dependencies to end
## up in a subdir. Having to rename by hand is ugly.
## (We might end up doing this anyway to support other compilers.)
## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like
## -MM, not -M (despite what the docs say).
## - Using -M directly means running the compiler twice (even worse
## than renaming).
if test -z "$gccflag"; then
gccflag=-MD,
fi
"$@" -Wp,"$gccflag$tmpdepfile"
stat=$?
if test $stat -eq 0; then :
else
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
echo "$object : \\" > "$depfile"
alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
## The second -e expression handles DOS-style file names with drive letters.
sed -e 's/^[^:]*: / /' \
-e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile"
## This next piece of magic avoids the `deleted header file' problem.
## The problem is that when a header file which appears in a .P file
## is deleted, the dependency causes make to die (because there is
## typically no way to rebuild the header). We avoid this by adding
## dummy dependencies for each header file. Too bad gcc doesn't do
## this for us directly.
tr ' ' '
' < "$tmpdepfile" |
## Some versions of gcc put a space before the `:'. On the theory
## that the space means something, we add a space to the output as
## well.
## Some versions of the HPUX 10.20 sed can't process this invocation
## correctly. Breaking it into two sed invocations is a workaround.
sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile"
;;
hp)
# This case exists only to let depend.m4 do its work. It works by
# looking at the text of this script. This case will never be run,
# since it is checked for above.
exit 1
;;
sgi)
if test "$libtool" = yes; then
"$@" "-Wp,-MDupdate,$tmpdepfile"
else
"$@" -MDupdate "$tmpdepfile"
fi
stat=$?
if test $stat -eq 0; then :
else
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files
echo "$object : \\" > "$depfile"
# Clip off the initial element (the dependent). Don't try to be
# clever and replace this with sed code, as IRIX sed won't handle
# lines with more than a fixed number of characters (4096 in
# IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines;
# the IRIX cc adds comments like `#:fec' to the end of the
# dependency line.
tr ' ' '
' < "$tmpdepfile" \
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \
tr '
' ' ' >> $depfile
echo >> $depfile
# The second pass generates a dummy entry for each header file.
tr ' ' '
' < "$tmpdepfile" \
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \
>> $depfile
else
# The sourcefile does not contain any dependencies, so just
# store a dummy comment line, to avoid errors with the Makefile
# "include basename.Plo" scheme.
echo "#dummy" > "$depfile"
fi
rm -f "$tmpdepfile"
;;
aix)
# The C for AIX Compiler uses -M and outputs the dependencies
# in a .u file. In older versions, this file always lives in the
# current directory. Also, the AIX compiler puts `$object:' at the
# start of each line; $object doesn't have directory information.
# Version 6 uses the directory in both cases.
stripped=`echo "$object" | sed 's/\(.*\)\..*$/\1/'`
tmpdepfile="$stripped.u"
if test "$libtool" = yes; then
"$@" -Wc,-M
else
"$@" -M
fi
stat=$?
if test -f "$tmpdepfile"; then :
else
stripped=`echo "$stripped" | sed 's,^.*/,,'`
tmpdepfile="$stripped.u"
fi
if test $stat -eq 0; then :
else
rm -f "$tmpdepfile"
exit $stat
fi
if test -f "$tmpdepfile"; then
outname="$stripped.o"
# Each line is of the form `foo.o: dependent.h'.
# Do two passes, one to just change these to
# `$object: dependent.h' and one to simply `dependent.h:'.
sed -e "s,^$outname:,$object :," < "$tmpdepfile" > "$depfile"
sed -e "s,^$outname: \(.*\)$,\1:," < "$tmpdepfile" >> "$depfile"
else
# The sourcefile does not contain any dependencies, so just
# store a dummy comment line, to avoid errors with the Makefile
# "include basename.Plo" scheme.
echo "#dummy" > "$depfile"
fi
rm -f "$tmpdepfile"
;;
icc)
# Intel's C compiler understands `-MD -MF file'. However on
# icc -MD -MF foo.d -c -o sub/foo.o sub/foo.c
# ICC 7.0 will fill foo.d with something like
# foo.o: sub/foo.c
# foo.o: sub/foo.h
# which is wrong. We want:
# sub/foo.o: sub/foo.c
# sub/foo.o: sub/foo.h
# sub/foo.c:
# sub/foo.h:
# ICC 7.1 will output
# foo.o: sub/foo.c sub/foo.h
# and will wrap long lines using \ :
# foo.o: sub/foo.c ... \
# sub/foo.h ... \
# ...
"$@" -MD -MF "$tmpdepfile"
stat=$?
if test $stat -eq 0; then :
else
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
# Each line is of the form `foo.o: dependent.h',
# or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'.
# Do two passes, one to just change these to
# `$object: dependent.h' and one to simply `dependent.h:'.
sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile"
# Some versions of the HPUX 10.20 sed can't process this invocation
# correctly. Breaking it into two sed invocations is a workaround.
sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" |
sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile"
;;
tru64)
# The Tru64 compiler uses -MD to generate dependencies as a side
# effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'.
# At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put
# dependencies in `foo.d' instead, so we check for that too.
# Subdirectories are respected.
dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
test "x$dir" = "x$object" && dir=
base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'`
if test "$libtool" = yes; then
# With Tru64 cc, shared objects can also be used to make a
# static library. This mecanism is used in libtool 1.4 series to
# handle both shared and static libraries in a single compilation.
# With libtool 1.4, dependencies were output in $dir.libs/$base.lo.d.
#
# With libtool 1.5 this exception was removed, and libtool now
# generates 2 separate objects for the 2 libraries. These two
# compilations output dependencies in in $dir.libs/$base.o.d and
# in $dir$base.o.d. We have to check for both files, because
# one of the two compilations can be disabled. We should prefer
# $dir$base.o.d over $dir.libs/$base.o.d because the latter is
# automatically cleaned when .libs/ is deleted, while ignoring
# the former would cause a distcleancheck panic.
tmpdepfile1=$dir.libs/$base.lo.d # libtool 1.4
tmpdepfile2=$dir$base.o.d # libtool 1.5
tmpdepfile3=$dir.libs/$base.o.d # libtool 1.5
tmpdepfile4=$dir.libs/$base.d # Compaq CCC V6.2-504
"$@" -Wc,-MD
else
tmpdepfile1=$dir$base.o.d
tmpdepfile2=$dir$base.d
tmpdepfile3=$dir$base.d
tmpdepfile4=$dir$base.d
"$@" -MD
fi
stat=$?
if test $stat -eq 0; then :
else
rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4"
exit $stat
fi
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4"
do
test -f "$tmpdepfile" && break
done
if test -f "$tmpdepfile"; then
sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile"
# That's a tab and a space in the [].
sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile"
else
echo "#dummy" > "$depfile"
fi
rm -f "$tmpdepfile"
;;
#nosideeffect)
# This comment above is used by automake to tell side-effect
# dependency tracking mechanisms from slower ones.
dashmstdout)
# Important note: in order to support this mode, a compiler *must*
# always write the preprocessed file to stdout, regardless of -o.
"$@" || exit $?
# Remove the call to Libtool.
if test "$libtool" = yes; then
while test $1 != '--mode=compile'; do
shift
done
shift
fi
# Remove `-o $object'.
IFS=" "
for arg
do
case $arg in
-o)
shift
;;
$object)
shift
;;
*)
set fnord "$@" "$arg"
shift # fnord
shift # $arg
;;
esac
done
test -z "$dashmflag" && dashmflag=-M
# Require at least two characters before searching for `:'
# in the target name. This is to cope with DOS-style filenames:
# a dependency such as `c:/foo/bar' could be seen as target `c' otherwise.
"$@" $dashmflag |
sed 's:^[ ]*[^: ][^:][^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile"
rm -f "$depfile"
cat < "$tmpdepfile" > "$depfile"
tr ' ' '
' < "$tmpdepfile" | \
## Some versions of the HPUX 10.20 sed can't process this invocation
## correctly. Breaking it into two sed invocations is a workaround.
sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile"
;;
dashXmstdout)
# This case only exists to satisfy depend.m4. It is never actually
# run, as this mode is specially recognized in the preamble.
exit 1
;;
makedepend)
"$@" || exit $?
# Remove any Libtool call
if test "$libtool" = yes; then
while test $1 != '--mode=compile'; do
shift
done
shift
fi
# X makedepend
shift
cleared=no
for arg in "$@"; do
case $cleared in
no)
set ""; shift
cleared=yes ;;
esac
case "$arg" in
-D*|-I*)
set fnord "$@" "$arg"; shift ;;
# Strip any option that makedepend may not understand. Remove
# the object too, otherwise makedepend will parse it as a source file.
-*|$object)
;;
*)
set fnord "$@" "$arg"; shift ;;
esac
done
obj_suffix="`echo $object | sed 's/^.*\././'`"
touch "$tmpdepfile"
${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@"
rm -f "$depfile"
cat < "$tmpdepfile" > "$depfile"
sed '1,2d' "$tmpdepfile" | tr ' ' '
' | \
## Some versions of the HPUX 10.20 sed can't process this invocation
## correctly. Breaking it into two sed invocations is a workaround.
sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile" "$tmpdepfile".bak
;;
cpp)
# Important note: in order to support this mode, a compiler *must*
# always write the preprocessed file to stdout.
"$@" || exit $?
# Remove the call to Libtool.
if test "$libtool" = yes; then
while test $1 != '--mode=compile'; do
shift
done
shift
fi
# Remove `-o $object'.
IFS=" "
for arg
do
case $arg in
-o)
shift
;;
$object)
shift
;;
*)
set fnord "$@" "$arg"
shift # fnord
shift # $arg
;;
esac
done
"$@" -E |
sed -n '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' |
sed '$ s: \\$::' > "$tmpdepfile"
rm -f "$depfile"
echo "$object : \\" > "$depfile"
cat < "$tmpdepfile" >> "$depfile"
sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile"
rm -f "$tmpdepfile"
;;
msvisualcpp)
# Important note: in order to support this mode, a compiler *must*
# always write the preprocessed file to stdout, regardless of -o,
# because we must use -o when running libtool.
"$@" || exit $?
IFS=" "
for arg
do
case "$arg" in
"-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI")
set fnord "$@"
shift
shift
;;
*)
set fnord "$@" "$arg"
shift
shift
;;
esac
done
"$@" -E |
sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::echo "`cygpath -u \\"\1\\"`":p' | sort | uniq > "$tmpdepfile"
rm -f "$depfile"
echo "$object : \\" > "$depfile"
. "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile"
echo " " >> "$depfile"
. "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s::\1\::p' >> "$depfile"
rm -f "$tmpdepfile"
;;
none)
exec "$@"
;;
*)
echo "Unknown depmode $depmode" 1>&2
exit 1
;;
esac
exit 0
# Local Variables:
# mode: shell-script
# sh-indentation: 2
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-end: "$"
# End:

323
config/install-sh Executable file
View File

@ -0,0 +1,323 @@
#!/bin/sh
# install - install a program, script, or datafile
scriptversion=2005-02-02.21
# This originates from X11R5 (mit/util/scripts/install.sh), which was
# later released in X11R6 (xc/config/util/install.sh) with the
# following copyright and license.
#
# Copyright (C) 1994 X Consortium
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
# deal in the Software without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
# sell copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
# Except as contained in this notice, the name of the X Consortium shall not
# be used in advertising or otherwise to promote the sale, use or other deal-
# ings in this Software without prior written authorization from the X Consor-
# tium.
#
#
# FSF changes to this file are in the public domain.
#
# Calling this script install-sh is preferred over install.sh, to prevent
# `make' implicit rules from creating a file called install from it
# when there is no Makefile.
#
# This script is compatible with the BSD install script, but was written
# from scratch. It can only install one file at a time, a restriction
# shared with many OS's install programs.
# set DOITPROG to echo to test this script
# Don't use :- since 4.3BSD and earlier shells don't like it.
doit="${DOITPROG-}"
# put in absolute paths if you don't have them in your path; or use env. vars.
mvprog="${MVPROG-mv}"
cpprog="${CPPROG-cp}"
chmodprog="${CHMODPROG-chmod}"
chownprog="${CHOWNPROG-chown}"
chgrpprog="${CHGRPPROG-chgrp}"
stripprog="${STRIPPROG-strip}"
rmprog="${RMPROG-rm}"
mkdirprog="${MKDIRPROG-mkdir}"
chmodcmd="$chmodprog 0755"
chowncmd=
chgrpcmd=
stripcmd=
rmcmd="$rmprog -f"
mvcmd="$mvprog"
src=
dst=
dir_arg=
dstarg=
no_target_directory=
usage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
or: $0 [OPTION]... SRCFILES... DIRECTORY
or: $0 [OPTION]... -t DIRECTORY SRCFILES...
or: $0 [OPTION]... -d DIRECTORIES...
In the 1st form, copy SRCFILE to DSTFILE.
In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
In the 4th, create DIRECTORIES.
Options:
-c (ignored)
-d create directories instead of installing files.
-g GROUP $chgrpprog installed files to GROUP.
-m MODE $chmodprog installed files to MODE.
-o USER $chownprog installed files to USER.
-s $stripprog installed files.
-t DIRECTORY install into DIRECTORY.
-T report an error if DSTFILE is a directory.
--help display this help and exit.
--version display version info and exit.
Environment variables override the default commands:
CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG
"
while test -n "$1"; do
case $1 in
-c) shift
continue;;
-d) dir_arg=true
shift
continue;;
-g) chgrpcmd="$chgrpprog $2"
shift
shift
continue;;
--help) echo "$usage"; exit $?;;
-m) chmodcmd="$chmodprog $2"
shift
shift
continue;;
-o) chowncmd="$chownprog $2"
shift
shift
continue;;
-s) stripcmd=$stripprog
shift
continue;;
-t) dstarg=$2
shift
shift
continue;;
-T) no_target_directory=true
shift
continue;;
--version) echo "$0 $scriptversion"; exit $?;;
*) # When -d is used, all remaining arguments are directories to create.
# When -t is used, the destination is already specified.
test -n "$dir_arg$dstarg" && break
# Otherwise, the last argument is the destination. Remove it from $@.
for arg
do
if test -n "$dstarg"; then
# $@ is not empty: it contains at least $arg.
set fnord "$@" "$dstarg"
shift # fnord
fi
shift # arg
dstarg=$arg
done
break;;
esac
done
if test -z "$1"; then
if test -z "$dir_arg"; then
echo "$0: no input file specified." >&2
exit 1
fi
# It's OK to call `install-sh -d' without argument.
# This can happen when creating conditional directories.
exit 0
fi
for src
do
# Protect names starting with `-'.
case $src in
-*) src=./$src ;;
esac
if test -n "$dir_arg"; then
dst=$src
src=
if test -d "$dst"; then
mkdircmd=:
chmodcmd=
else
mkdircmd=$mkdirprog
fi
else
# Waiting for this to be detected by the "$cpprog $src $dsttmp" command
# might cause directories to be created, which would be especially bad
# if $src (and thus $dsttmp) contains '*'.
if test ! -f "$src" && test ! -d "$src"; then
echo "$0: $src does not exist." >&2
exit 1
fi
if test -z "$dstarg"; then
echo "$0: no destination specified." >&2
exit 1
fi
dst=$dstarg
# Protect names starting with `-'.
case $dst in
-*) dst=./$dst ;;
esac
# If destination is a directory, append the input filename; won't work
# if double slashes aren't ignored.
if test -d "$dst"; then
if test -n "$no_target_directory"; then
echo "$0: $dstarg: Is a directory" >&2
exit 1
fi
dst=$dst/`basename "$src"`
fi
fi
# This sed command emulates the dirname command.
dstdir=`echo "$dst" | sed -e 's,/*$,,;s,[^/]*$,,;s,/*$,,;s,^$,.,'`
# Make sure that the destination directory exists.
# Skip lots of stat calls in the usual case.
if test ! -d "$dstdir"; then
defaultIFS='
'
IFS="${IFS-$defaultIFS}"
oIFS=$IFS
# Some sh's can't handle IFS=/ for some reason.
IFS='%'
set x `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'`
shift
IFS=$oIFS
pathcomp=
while test $# -ne 0 ; do
pathcomp=$pathcomp$1
shift
if test ! -d "$pathcomp"; then
$mkdirprog "$pathcomp"
# mkdir can fail with a `File exist' error in case several
# install-sh are creating the directory concurrently. This
# is OK.
test -d "$pathcomp" || exit
fi
pathcomp=$pathcomp/
done
fi
if test -n "$dir_arg"; then
$doit $mkdircmd "$dst" \
&& { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \
&& { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \
&& { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \
&& { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; }
else
dstfile=`basename "$dst"`
# Make a couple of temp file names in the proper directory.
dsttmp=$dstdir/_inst.$$_
rmtmp=$dstdir/_rm.$$_
# Trap to clean up those temp files at exit.
trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
trap '(exit $?); exit' 1 2 13 15
# Copy the file name to the temp name.
$doit $cpprog "$src" "$dsttmp" &&
# and set any options; do chmod last to preserve setuid bits.
#
# If any of these fail, we abort the whole thing. If we want to
# ignore errors from any of these, just make sure not to ignore
# errors from the above "$doit $cpprog $src $dsttmp" command.
#
{ test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \
&& { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \
&& { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \
&& { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } &&
# Now rename the file to the real destination.
{ $doit $mvcmd -f "$dsttmp" "$dstdir/$dstfile" 2>/dev/null \
|| {
# The rename failed, perhaps because mv can't rename something else
# to itself, or perhaps because mv is so ancient that it does not
# support -f.
# Now remove or move aside any old file at destination location.
# We try this two ways since rm can't unlink itself on some
# systems and the destination file might be busy for other
# reasons. In this case, the final cleanup might fail but the new
# file should still install successfully.
{
if test -f "$dstdir/$dstfile"; then
$doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \
|| $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \
|| {
echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2
(exit 1); exit 1
}
else
:
fi
} &&
# Now rename the file to the real destination.
$doit $mvcmd "$dsttmp" "$dstdir/$dstfile"
}
}
fi || { (exit 1); exit 1; }
done
# The final little trick to "correctly" pass the exit status to the exit trap.
{
(exit 0); exit 0
}
# Local variables:
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-end: "$"
# End:

357
config/missing Executable file
View File

@ -0,0 +1,357 @@
#! /bin/sh
# Common stub for a few missing GNU programs while installing.
scriptversion=2005-02-08.22
# Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005
# Free Software Foundation, Inc.
# Originally by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996.
# 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 2, 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, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
# 02111-1307, USA.
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
if test $# -eq 0; then
echo 1>&2 "Try \`$0 --help' for more information"
exit 1
fi
run=:
# In the cases where this matters, `missing' is being run in the
# srcdir already.
if test -f configure.ac; then
configure_ac=configure.ac
else
configure_ac=configure.in
fi
msg="missing on your system"
case "$1" in
--run)
# Try to run requested program, and just exit if it succeeds.
run=
shift
"$@" && exit 0
# Exit code 63 means version mismatch. This often happens
# when the user try to use an ancient version of a tool on
# a file that requires a minimum version. In this case we
# we should proceed has if the program had been absent, or
# if --run hadn't been passed.
if test $? = 63; then
run=:
msg="probably too old"
fi
;;
-h|--h|--he|--hel|--help)
echo "\
$0 [OPTION]... PROGRAM [ARGUMENT]...
Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an
error status if there is no known handling for PROGRAM.
Options:
-h, --help display this help and exit
-v, --version output version information and exit
--run try to run the given command, and emulate it if it fails
Supported PROGRAM values:
aclocal touch file \`aclocal.m4'
autoconf touch file \`configure'
autoheader touch file \`config.h.in'
automake touch all \`Makefile.in' files
bison create \`y.tab.[ch]', if possible, from existing .[ch]
flex create \`lex.yy.c', if possible, from existing .c
help2man touch the output file
lex create \`lex.yy.c', if possible, from existing .c
makeinfo touch the output file
tar try tar, gnutar, gtar, then tar without non-portable flags
yacc create \`y.tab.[ch]', if possible, from existing .[ch]
Send bug reports to <bug-automake@gnu.org>."
exit $?
;;
-v|--v|--ve|--ver|--vers|--versi|--versio|--version)
echo "missing $scriptversion (GNU Automake)"
exit $?
;;
-*)
echo 1>&2 "$0: Unknown \`$1' option"
echo 1>&2 "Try \`$0 --help' for more information"
exit 1
;;
esac
# Now exit if we have it, but it failed. Also exit now if we
# don't have it and --version was passed (most likely to detect
# the program).
case "$1" in
lex|yacc)
# Not GNU programs, they don't have --version.
;;
tar)
if test -n "$run"; then
echo 1>&2 "ERROR: \`tar' requires --run"
exit 1
elif test "x$2" = "x--version" || test "x$2" = "x--help"; then
exit 1
fi
;;
*)
if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
# We have it, but it failed.
exit 1
elif test "x$2" = "x--version" || test "x$2" = "x--help"; then
# Could not run --version or --help. This is probably someone
# running `$TOOL --version' or `$TOOL --help' to check whether
# $TOOL exists and not knowing $TOOL uses missing.
exit 1
fi
;;
esac
# If it does not exist, or fails to run (possibly an outdated version),
# try to emulate it.
case "$1" in
aclocal*)
echo 1>&2 "\
WARNING: \`$1' is $msg. You should only need it if
you modified \`acinclude.m4' or \`${configure_ac}'. You might want
to install the \`Automake' and \`Perl' packages. Grab them from
any GNU archive site."
touch aclocal.m4
;;
autoconf)
echo 1>&2 "\
WARNING: \`$1' is $msg. You should only need it if
you modified \`${configure_ac}'. You might want to install the
\`Autoconf' and \`GNU m4' packages. Grab them from any GNU
archive site."
touch configure
;;
autoheader)
echo 1>&2 "\
WARNING: \`$1' is $msg. You should only need it if
you modified \`acconfig.h' or \`${configure_ac}'. You might want
to install the \`Autoconf' and \`GNU m4' packages. Grab them
from any GNU archive site."
files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}`
test -z "$files" && files="config.h"
touch_files=
for f in $files; do
case "$f" in
*:*) touch_files="$touch_files "`echo "$f" |
sed -e 's/^[^:]*://' -e 's/:.*//'`;;
*) touch_files="$touch_files $f.in";;
esac
done
touch $touch_files
;;
automake*)
echo 1>&2 "\
WARNING: \`$1' is $msg. You should only need it if
you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'.
You might want to install the \`Automake' and \`Perl' packages.
Grab them from any GNU archive site."
find . -type f -name Makefile.am -print |
sed 's/\.am$/.in/' |
while read f; do touch "$f"; done
;;
autom4te)
echo 1>&2 "\
WARNING: \`$1' is needed, but is $msg.
You might have modified some files without having the
proper tools for further handling them.
You can get \`$1' as part of \`Autoconf' from any GNU
archive site."
file=`echo "$*" | sed -n 's/.*--output[ =]*\([^ ]*\).*/\1/p'`
test -z "$file" && file=`echo "$*" | sed -n 's/.*-o[ ]*\([^ ]*\).*/\1/p'`
if test -f "$file"; then
touch $file
else
test -z "$file" || exec >$file
echo "#! /bin/sh"
echo "# Created by GNU Automake missing as a replacement of"
echo "# $ $@"
echo "exit 0"
chmod +x $file
exit 1
fi
;;
bison|yacc)
echo 1>&2 "\
WARNING: \`$1' $msg. You should only need it if
you modified a \`.y' file. You may need the \`Bison' package
in order for those modifications to take effect. You can get
\`Bison' from any GNU archive site."
rm -f y.tab.c y.tab.h
if [ $# -ne 1 ]; then
eval LASTARG="\${$#}"
case "$LASTARG" in
*.y)
SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'`
if [ -f "$SRCFILE" ]; then
cp "$SRCFILE" y.tab.c
fi
SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'`
if [ -f "$SRCFILE" ]; then
cp "$SRCFILE" y.tab.h
fi
;;
esac
fi
if [ ! -f y.tab.h ]; then
echo >y.tab.h
fi
if [ ! -f y.tab.c ]; then
echo 'main() { return 0; }' >y.tab.c
fi
;;
lex|flex)
echo 1>&2 "\
WARNING: \`$1' is $msg. You should only need it if
you modified a \`.l' file. You may need the \`Flex' package
in order for those modifications to take effect. You can get
\`Flex' from any GNU archive site."
rm -f lex.yy.c
if [ $# -ne 1 ]; then
eval LASTARG="\${$#}"
case "$LASTARG" in
*.l)
SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'`
if [ -f "$SRCFILE" ]; then
cp "$SRCFILE" lex.yy.c
fi
;;
esac
fi
if [ ! -f lex.yy.c ]; then
echo 'main() { return 0; }' >lex.yy.c
fi
;;
help2man)
echo 1>&2 "\
WARNING: \`$1' is $msg. You should only need it if
you modified a dependency of a manual page. You may need the
\`Help2man' package in order for those modifications to take
effect. You can get \`Help2man' from any GNU archive site."
file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'`
if test -z "$file"; then
file=`echo "$*" | sed -n 's/.*--output=\([^ ]*\).*/\1/p'`
fi
if [ -f "$file" ]; then
touch $file
else
test -z "$file" || exec >$file
echo ".ab help2man is required to generate this page"
exit 1
fi
;;
makeinfo)
echo 1>&2 "\
WARNING: \`$1' is $msg. You should only need it if
you modified a \`.texi' or \`.texinfo' file, or any other file
indirectly affecting the aspect of the manual. The spurious
call might also be the consequence of using a buggy \`make' (AIX,
DU, IRIX). You might want to install the \`Texinfo' package or
the \`GNU make' package. Grab either from any GNU archive site."
# The file to touch is that specified with -o ...
file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'`
if test -z "$file"; then
# ... or it is the one specified with @setfilename ...
infile=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'`
file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $infile`
# ... or it is derived from the source name (dir/f.texi becomes f.info)
test -z "$file" && file=`echo "$infile" | sed 's,.*/,,;s,.[^.]*$,,'`.info
fi
touch $file
;;
tar)
shift
# We have already tried tar in the generic part.
# Look for gnutar/gtar before invocation to avoid ugly error
# messages.
if (gnutar --version > /dev/null 2>&1); then
gnutar "$@" && exit 0
fi
if (gtar --version > /dev/null 2>&1); then
gtar "$@" && exit 0
fi
firstarg="$1"
if shift; then
case "$firstarg" in
*o*)
firstarg=`echo "$firstarg" | sed s/o//`
tar "$firstarg" "$@" && exit 0
;;
esac
case "$firstarg" in
*h*)
firstarg=`echo "$firstarg" | sed s/h//`
tar "$firstarg" "$@" && exit 0
;;
esac
fi
echo 1>&2 "\
WARNING: I can't seem to be able to run \`tar' with the given arguments.
You may want to install GNU tar or Free paxutils, or check the
command line arguments."
exit 1
;;
*)
echo 1>&2 "\
WARNING: \`$1' is needed, and is $msg.
You might have modified some files without having the
proper tools for further handling them. Check the \`README' file,
it often tells you about the needed prerequisites for installing
this package. You may also peek at any GNU archive site, in case
some other package would contain this missing \`$1' program."
exit 1
;;
esac
exit 0
# Local variables:
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-end: "$"
# End:

10606
configure vendored Executable file

File diff suppressed because it is too large Load Diff

295
configure.ac Normal file
View File

@ -0,0 +1,295 @@
#
# Host Identity Protocol
# Copyright (c) 2006 the Boeing Comapny
#
# 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 2 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.
#
# configure.ac
#
# Author: Jeff Ahrenholz <jeffrey.m.ahrenholz@boeing.com>
#
#
# -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.
AC_PREREQ(2.59)
# change the HIP version here
AC_INIT(OpenHIP, 0.6, [openhip-developers@lists.sourceforge.net], openhip)
AC_CONFIG_SRCDIR([src/protocol/hip_main.c])
AC_CONFIG_AUX_DIR(config)
AM_CONFIG_HEADER([config.h])
AM_INIT_AUTOMAKE
# Default compiler flags, to avoid using -g with release files.
AC_GNU_SOURCE
CFLAGS="$CFLAGS -O3 -Werror -D_GNU_SOURCE"
# HIP files go in /etc/hip or /usr/local/etc/hip
sysconfdir=$sysconfdir/hip
# Checks for programs.
AC_PROG_AWK
AC_PROG_CC
AM_PROG_CC_C_O
# Checks for libraries.
AC_CHECK_LIB([crypto], [AES_cbc_encrypt])
if test "x$ac_cv_lib_crypto_AES_cbc_encrypt" != "xyes"; then
AC_MSG_ERROR([Could not find AES functions from OpenSSL. Make sure the openssl-devel package is installed or that you have installed the suitable source.])
fi
AC_CHECK_LIB([crypto], [RSA_verify])
if test "x$ac_cv_lib_crypto_RSA_verify" != "xyes"; then
AC_MSG_ERROR([Could not find RSA functions from OpenSSL. Make sure the openssl-devel package is installed or that you have installed the suitable source.])
fi
#
# configure option to define SMA_CRAWLER
AC_CHECK_LIB([pthread], [pthread_create])
# FIXME: Replace `main' with a function in `-li3', `-li3client':
#AC_CHECK_LIB([i3], [main])
#AC_CHECK_LIB([i3client], [main])
# FIXME: Replace `main' with a function in `-liphlpapi':
#AC_CHECK_LIB([iphlpapi], [])
AC_CHECK_LIB([ipsec], [pfkey_send_hip_x1])
# FIXME: Replace `main' with a function in `-lutils':
#AC_CHECK_LIB([utils], [main])
# Checks for header files.
AC_HEADER_STDC
AC_HEADER_SYS_WAIT
AC_CHECK_HEADERS([arpa/inet.h fcntl.h netdb.h netinet/in.h stdlib.h string.h sys/ioctl.h sys/socket.h sys/time.h unistd.h])
# Checks for typedefs, structures, and compiler characteristics.
AC_C_CONST
AC_C_INLINE
AC_TYPE_SIZE_T
AC_HEADER_TIME
# Checks for library functions.
AC_FUNC_FORK
AC_PROG_GCC_TRADITIONAL
AC_FUNC_MALLOC
AC_FUNC_MEMCMP
AC_FUNC_SELECT_ARGTYPES
AC_TYPE_SIGNAL
AC_FUNC_VPRINTF
AC_CHECK_FUNCS([bzero gethostbyname gethostname gettimeofday inet_ntoa memmove memset pow select socket strchr strerror strncasecmp strrchr strstr uname])
CFLAGS="$CFLAGS -Wall -DCONFIG_HIP -DSYSCONFDIR=\"\\\"\$(sysconfdir)\\\"\" -DLOCALSTATEDIR=\"\\\"\$(localstatedir)\\\"\" "
# -Wno-unused
AC_MSG_CHECKING(if --enable-kernel-support option is specified)
AC_ARG_ENABLE(kernel-support,
[ --enable-kernel-support enable Linux kernel support],
[enable_kernel=$enable_kernel_support
AC_MSG_RESULT(yes)],
[enable_kernel=default
AC_MSG_RESULT(no)])
AC_MSG_CHECKING(if --enable-sma-crawler option is specified)
AC_ARG_ENABLE(sma-crawler,
[ --enable-sma-crawler enable SMA crawler extensions],
[enable_sma_crawler=$enable_sma_crawler
AC_MSG_RESULT(yes)],
[enable_sma_crawler=default
AC_MSG_RESULT(no)])
AC_MSG_CHECKING(if --enable-mobile-router option is specified)
AC_ARG_ENABLE(mobile-router,
[ --enable-mobile-router enable mobile router server extensions],
[enable_mobile_router=$enable_mobile_router
AC_MSG_RESULT(yes)],
[enable_mobile_router=default
AC_MSG_RESULT(no)])
#
# Kernel detection - determines whether to build hipd for use with a HIP kernel
################################################################################
# check for pfkeyv2.h
# set kernel_support = yes/no
kernel_support=no
AC_CANONICAL_HOST
case "$host_os" in
*linux*)
AC_MSG_CHECKING(for Linux kernel headers)
AC_ARG_WITH(kernel-headers,
AC_HELP_STRING([--with-kernel-headers=/lib/modules/<uname>build/include],
[where your Linux kernel headers are installed]),
[ KERNEL_INCLUDE="$with_kernel_headers"
CONFIGURE_AMFLAGS="--with-kernel-headers=$with_kernel_headers"
AC_SUBST(CONFIGURE_AMGFLAGS) ],
[ KERNEL_INCLUDE="/lib/modules/`uname -r`/build/include" ])
AC_CHECK_HEADER([$KERNEL_INCLUDE/linux/pfkeyv2.h],
[kernel_support=yes],
[ AC_CHECK_HEADER(/usr/src/linux/include/linux/pfkeyv2.h,
[ KERNEL_INCLUDE=/usr/src/linux/include
kernel_support=yes],
[kernel_support=no])
])
if test "$kernel_support" = "yes"; then
#AC_TRY_RUN
# AC_DEFINE(CONFIG_HIP)
AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM([[#include "$KERNEL_INCLUDE/linux/pfkeyv2.h"]],
[[if (SADB_HIP_ACQUIRE < SADB_HIP_ADD) return 0; else return 99; ]])],
[AC_MSG_RESULT([HIP patch was found in pfkeyv2.h.])
kernel_support=yes],
[AC_MSG_RESULT([HIP patch missing from pfkeyv2.h.])
kernel_support=no] )
# AC_UNDEFINE(CONFIG_HIP)
AC_MSG_CHECKING(if kernel has HIP patch)
AC_MSG_RESULT($kernel_support)
fi
#AC_SUBST(KERNEL_INCLUDE)
;;
*)
kernel_support=no
;;
esac
# check configure option vs detected kernel
if test "$enable_kernel_support" = "yes"; then
if test "$kernel_support" = "no" ; then
AC_MSG_ERROR([Kernel support requested, but HIP kernel not found! Aborting.])
else
want_kernel=true
fi
else
if test "$enable_kernel_support" = "no"; then
want_kernel=false
else
# unspecified
if test "$kernel_support" = "yes"; then
want_kernel=true
else
want_kernel=false
fi
fi
fi
if test $want_kernel = true; then
CFLAGS="-I$KERNEL_INCLUDE $CFLAGS"
fi
# extra check to make sure libipsec is patched if
# we are going to compile kernel support
if test "$kernel_support" = "yes"; then
if test "x$ac_cv_lib_ipsec_pfkey_send_hip_x1" = "xyes"; then
AC_MSG_RESULT([Kernel and libipsec HIP patches OK!]);
else
AC_MSG_ERROR([Kernel has HIP patch but libipsec has not been patched with HIP patch.])
fi
fi
#
# configure option to define SMA_CRAWLER
################################################################################
if test "$enable_sma_crawler" = "yes"; then
want_sma_crawler=true
CFLAGS=" -DSMA_CRAWLER $CFLAGS"
AC_CHECK_LIB([ssl], [SSL_library_init])
if test "x$ac_cv_lib_ssl_SSL_library_init" = "xyes"; then
AC_MSG_RESULT([OpenSSL library found for SMA crawler extensions])
else
AC_MSG_ERROR([SMA crawler extensions requested but OpenSSL library not found.])
fi
AC_CHECK_LIB([opensc], [sc_connect_card])
if test "x$ac_cv_lib_opensc_sc_connect_card" = "xyes"; then
AC_MSG_RESULT([OpenSC smart card library found for SMA crawler extensions])
else
AC_MSG_ERROR([SMA crawler extensions requested but OpenSC smart card library not found.])
fi
else
want_sma_crawler=false
fi
#
# HIP mobile router server extensions
################################################################################
# check to make sure libipq is present if we are going to compile
# mobile router support
want_mobile_router=false
if test "x$enable_mobile_router" = "xyes"; then
AC_CHECK_LIB([ipq], [ipq_create_handle])
if test "x$ac_cv_lib_ipq_ipq_create_handle" = "xyes"; then
CFLAGS="$CFLAGS -DMOBILE_ROUTER"
want_mobile_router=true
else
AC_MSG_ERROR([mobile router server extensions requested but libipq not found! Aborting.])
fi
fi
#
# Mac OS X detection
################################################################################
want_osx=false
case "${host}" in
*-apple-darwin*)
want_osx=true
;;
esac
# Automake conditionals
################################################################################
AM_CONDITIONAL(WANT_KERNEL, test x$want_kernel = xtrue)
AM_CONDITIONAL(WANT_SMA_CRAWLER, test x$want_sma_crawler = xtrue)
AM_CONDITIONAL(WANT_MOBILE_ROUTER, test x$want_mobile_router = xtrue)
AM_CONDITIONAL(WANT_OSX, test x$want_osx = xtrue)
#AC_SUBST(WANT_KERNEL, $want_kernel)
PKG_CHECK_MODULES(HIP, libxml-2.0)
AC_CONFIG_FILES([src/include/hip/hip_version.h
src/linux/openhip.spec
src/linux/deb/control
src/win32/install-win32/openhip.nsi
docs/Doxyfile
Makefile
src/Makefile
docs/Makefile])
AC_OUTPUT
#
# Summary message at the end of configure output. Keep this pretty.
################################################################################
AC_MSG_NOTICE([ ])
AC_MSG_NOTICE([=== Finished configuring $PACKAGE_STRING: ===])
AC_MSG_NOTICE([ ])
AC_MSG_NOTICE([ - building HIP user mode binary 'hip'])
AC_MSG_NOTICE([ ])
AC_MSG_NOTICE([ - building 'hitgen' utility])
AC_MSG_NOTICE([ ])
if test $want_kernel = true; then
AC_MSG_NOTICE([ - building HIP daemon 'hipd' for kernel mode])
else
AC_MSG_NOTICE([ - NOT building HIP daemon 'hipd' for kernel mode])
fi
AC_MSG_NOTICE([ ])
if test $want_sma_crawler = true; then
AC_MSG_NOTICE([ - building HIP SMA crawler extensions])
else
AC_MSG_NOTICE([ - NOT building HIP SMA crawler extensions])
fi
AC_MSG_NOTICE([ ])
if test $want_mobile_router = true; then
AC_MSG_NOTICE([ - building mobile router server extensions])
else
AC_MSG_NOTICE([ - NOT building mobile router server extensions])
fi
AC_MSG_NOTICE([ ])

1237
docs/Doxyfile.in Normal file

File diff suppressed because it is too large Load Diff

28
docs/Makefile.am Normal file
View File

@ -0,0 +1,28 @@
#
# Host Identity Protocol
# Copyright (c) 2006 the Boeing Comapny
#
# 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 2 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.
#
# Makefile.am
#
# Author: Jeff Ahrenholz <jeffrey.m.ahrenholz@boeing.com>
#
#
all:
docs: Doxyfile
doxygen Doxyfile
clean:
rm -rf html
rm -rf latex

16
docs/main.txt Normal file
View File

@ -0,0 +1,16 @@
/**
* \mainpage Doxygen support for OpenHIP
*
* The software is split across a number of different CVS modules:
* - <code>hip:</code> User-space protocol engine for HIP
* - <code>hipd:</code> Legacy (pre-0.4 release) branch of current
* <code>hip</code> module (obsolete)
* - <code>patches:</code> bind (DNS), Ethereal/Wireshark, ipsec-tools,
* and Linux kernel patches for HIP
*
*
* The <a href=http://www.openhip.org/wiki/index.php?title=Main_Page>OpenHIP
* wiki</a> is presently the source of most of our project documentation. This
* Doxygen directory contains source code cross reference of the raw
* (not doxygen-commented) APIs and data structures in the hip module only.
*/

103
src/Makefile.am Normal file
View File

@ -0,0 +1,103 @@
#
# Host Identity Protocol
# Copyright (c) 2006 the Boeing Comapny
#
# 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 2 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.
#
# Makefile.am
#
# Author: Jeff Ahrenholz <jeffrey.m.ahrenholz@boeing.com>
#
#
sbin_PROGRAMS = hitgen hip hipstatus
if WANT_KERNEL
sbin_PROGRAMS += hipd
endif
# HIP protocol source files
SRC_PROTO = protocol/hip_addr.c protocol/hip_cache.c protocol/hip_dht.c \
protocol/hip_globals.c protocol/hip_input.c \
protocol/hip_ipsec.c protocol/hip_keymat.c protocol/hip_main.c \
protocol/hip_output.c protocol/hip_status.c \
protocol/hip_stun.c protocol/hip_stun_udp.c
# Utility source files
SRC_UTIL = util/hip_util.c util/hip_xml.c
# Linux main files
SRC_MAIN_KERN = linux/hip_linux_main.c
SRC_MAIN_UMH = linux/hip_linux_umh.c
# Hitgen source files
SRC_HITGEN = util/hitgen.c util/hip_util.c protocol/hip_globals.c
hitgen_CFLAGS = -DHITGEN
if !WANT_KERNEL
hitgen_CFLAGS += -D__UMH__
endif
# Usermode version
hip_CFLAGS = -D__UMH__
SRC_USERMODE = usermode/hip_umh_main.c \
usermode/hip_dns.c usermode/hip_pfkey.c \
usermode/libipsec_stub.c usermode/hip_esp.c \
usermode/hip_sadb.c usermode/hip_status2.c
if WANT_MOBILE_ROUTER
SRC_USERMODE += usermode/hip_mr.c
endif
# Mac support
if WANT_OSX
hip_CFLAGS += -D__MACOSX__
hitgen_CFLAGS += -D__MACOSX__
SRC_USERMODE += mac/hip_mac.c
endif
INCLUDES = -I./include @HIP_CFLAGS@
LDADD = @HIP_LIBS@
# SMA craweler support
if WANT_SMA_CRAWLER
SRC_UTIL += util/cfg-api/hip_cfg_api.c
SRC_HITGEN += util/sc_utils.c
# SUBDIRS = util/cfg-ldap
endif
# i3 support
SRC_PROTO_I3 = protocol/i3_send.c protocol/i3_recv.c
# different targets
hitgen_SOURCES = $(SRC_HITGEN)
hipd_SOURCES = $(SRC_PROTO) $(SRC_UTIL) $(SRC_MAIN_KERN)
hip_SOURCES = $(SRC_PROTO) $(SRC_UTIL) $(SRC_MAIN_UMH) $(SRC_USERMODE)
hipstatus_SOURCES = util/usermode-status.c
# this would be nice to use, but it overwrites the file upon 'make install'
#dist_sysconf_DATA = ../conf/known_host_identities.xml
# make sure that HIP directories are available
install-data-hook:
test -d "$(DESTDIR)$(localstatedir)/log" || \
mkdir -p "$(DESTDIR)$(localstatedir)/log"
test -d "$(DESTDIR)$(localstatedir)/run" || \
mkdir -p "$(DESTDIR)$(localstatedir)/run"
test -d "$(DESTDIR)$(sysconfdir)" || mkdir -p "$(DESTDIR)$(sysconfdir)"
test -e "$(DESTDIR)$(sysconfdir)/known_host_identities.xml" || \
cp ../conf/known_host_identities.xml $(DESTDIR)$(sysconfdir)
@echo
@echo Configuration files will reside in $(DESTDIR)$(sysconfdir).
@echo " - run $(DESTDIR)$(sbindir)/hitgen -conf to generate"
@echo " a default $(DESTDIR)$(sysconfdir)/hip.conf file."
@echo " - run $(DESTDIR)$(sbindir)/hitgen (no parameters) to generate"
@echo " a $(DESTDIR)$(sysconfdir)/my_host_identities.xml file."
@echo

76
src/Makefile.mac.am Normal file
View File

@ -0,0 +1,76 @@
#
# Host Identity Protocol
# Copyright (c) 2006 the Boeing Comapny
#
# 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 2 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.
#
# Makefile.am
#
# Author: Jeff Ahrenholz <jeffrey.m.ahrenholz@boeing.com>
#
#
sbin_PROGRAMS = hitgen hip hipstatus
# HIP protocol source files
SRC_PROTO = protocol/hip_addr.c protocol/hip_cache.c protocol/hip_dht.c \
protocol/hip_globals.c protocol/hip_input.c \
protocol/hip_ipsec.c protocol/hip_keymat.c protocol/hip_main.c \
protocol/hip_output.c protocol/hip_status.c \
protocol/hip_stun.c protocol/hip_stun_udp.c
# Utility source files
SRC_UTIL = util/hip_util.c util/hip_xml.c
# Main files
SRC_MAIN_UMH = linux/hip_linux_umh.c
# Hitgen source files
SRC_HITGEN = util/hitgen.c util/hip_util.c protocol/hip_globals.c
# Usermode version
SRC_USERMODE = usermode/hip_umh_main.c \
usermode/hip_dns.c usermode/hip_pfkey.c \
usermode/libipsec_stub.c usermode/hip_esp.c \
usermode/hip_sadb.c usermode/hip_status2.c \
mac/hip_mac.c
# Mac support
#if WANT_OSX
hip_CFLAGS = -D__UMH__ -D__MACOSX__
hitgen_CFLAGS = -DHITGEN -D__MACOSX__
hipstatus_CFLAGS = -D__UMH__ -D__MACOSX__
#endif
INCLUDES = -I./include @HIP_CFLAGS@
LDADD = @HIP_LIBS@
# different targets
hitgen_SOURCES = $(SRC_HITGEN)
hip_SOURCES = $(SRC_PROTO) $(SRC_UTIL) $(SRC_MAIN_UMH) $(SRC_USERMODE)
hipstatus_SOURCES = util/usermode-status.c
# make sure that HIP directories are available
install-data-hook:
test -d "$(localstatedir)/log" || mkdir -p "$(localstatedir)/log"
test -d "$(localstatedir)/run" || mkdir -p "$(localstatedir)/run"
test -d "$(sysconfdir)" || mkdir -p "$(sysconfdir)"
test -e "$(sysconfdir)/known_host_identities.xml" || \
cp ../conf/known_host_identities.xml $(sysconfdir)
@echo
@echo Configuration files will reside in $(sysconfdir).
@echo " - run $(sbindir)/hitgen -conf to generate"
@echo " a default $(sysconfdir)/hip.conf file."
@echo " - run $(sbindir)/hitgen (no parameters) to generate"
@echo " a $(sysconfdir)/my_host_identities.xml file."
@echo

View File

@ -0,0 +1,52 @@
#ifndef __SMA_ENDBOX_UTILS__
#define __SMA_ENDBOX_UTILS__
#include <asm/types.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
/* #define _GNU_SOURCE */
#include <string.h>
#include <arpa/inet.h>
/* extern char *strndup(const char *, size_t); */
typedef struct _pList {
char *ip;
char *mac;
} pList;
typedef struct _spiList {
__u32 src;
__u32 dst;
__u32 spi;
struct _spiList *next;
} spiList;
typedef union _addrUnion {
__u64 s64;
struct {
__u32 src;
__u32 dst;
} c;
} addrUnion;
int read_private_hosts();
int read_hostmap();
void dump_private_hosts();
void dump_hostmap();
char *find_endbox(char *host);
char *find_endbox2(__u32 host);
int find_host(char *host);
int find_host2(__u32 host);
void read_endbox_config() ;
void addSpiEntry(__u32 spi, __u32 src, __u32 dst) ;
spiList *findSpiEntry(__u32 spi);
void endbox_init();
__u64 find_mac(__u32 host);
int find_address_extension(__u32 * src, __u32 *dst, __u8 *data);
#endif

78
src/include/hip/hip_cfg.h Normal file
View File

@ -0,0 +1,78 @@
#ifndef _HIPSPD_H_
#define _HIPSPD_H_
#include <netinet/in.h>
#include <netinet/ether.h>
#include <map>
#include <set>
#include <string>
#define HIT_SIZE 16
typedef __u8 hip_hit [HIT_SIZE];
using namespace std;
class certInfo
{
public:
certInfo(char *hit) { _hit = hit; time(&_ts);};
~certInfo();
time_t getTs() { return _ts; };
const char *getHit() { return _hit.c_str(); };
certInfo(){};
private:
string _hit;
time_t _ts;
};
class hitPair
{
public:
hitPair(const hip_hit hit1, const hip_hit hit2);
void print() const;
bool operator<(const hitPair & hp) const;
public:
hip_hit _hit1;
hip_hit _hit2;
};
struct hp_compare
{
bool operator ()(const hitPair & hp1, const hitPair & hp2)
{
return hp1 < hp2;
}
};
class hipCfg{
public:
hipCfg(){};
virtual ~hipCfg(){};
int hit_peer_allowed(const hip_hit hit1, const hip_hit hit2);
int peers_allowed(hip_hit *hits1, hip_hit *hits2, int max_cnt);
int legacyNodeToEndbox(const struct sockaddr *host, struct sockaddr *eb);
int endbox2Llip(const struct sockaddr *eb, struct sockaddr *llip);
int getLegacyNodesByEndbox(const struct sockaddr *eb,
struct sockaddr_storage *hosts, int size);
virtual int getLocalCertUrl(char *url, int size) = 0;
virtual int verifyCert(const char *url, const hip_hit hit) = 0;
virtual int postLocalCert(const char *hit) = 0;
virtual int loadCfg(struct hip_conf *hc) = 0;
static int hit2hitstr(char *hit_str, const hip_hit hit);
static int hitstr2lsistr(char *lsi_str, char *hit_str);
static int addr_to_str(const struct sockaddr *addr, char *data, int len);
static int hitstr2hit(hip_hit hit, char *hit_str);
static int hex_to_bin(char *src, char *dst, int dst_len);
static int str_to_addr(const char *data, struct sockaddr *addr);
protected:
map <string, string> _legacyNode2EndboxMap;
map <string, string> _endbox2LlipMap; /* endbox (LSI) to Llip (BCWIN) mapping */
string _localCertUrl;
map <string, certInfo> _certs; /* cached certificates data indexed by cert url*/
set <hitPair, hp_compare> _allowed_peers; /* pairs of hits allowed to start HIP base exchange */
};
#endif

View File

@ -0,0 +1,133 @@
#ifndef _HIPCFGAPI_H_
#define _HIPCFGAPI_H_
#include <sys/types.h>
#include <sys/socket.h>
#include <net/ethernet.h>
#include <hip/hip_types.h>
/* Input: the name of the dynamic link library
* e.g. the xml file based library "libhipcfg.so"
* Return: 0 if succeed, non-zero if error.
*/
#define hipcfg_init_fn "hipcfg_init"
extern int (*hipcfg_init_p)(struct hip_conf *hc);
extern int hipcfg_init(char *dlname, struct hip_conf *hc);
/* Input: the two peer hosts identified by their HITs
* Return: 1 if a HIP base exchange is allowed between the peers.
* 0 otherwise.
*/
#define hipcfg_allowed_peers_fn "hipcfg_allowed_peers"
extern int (*hipcfg_allowed_peers_p)(const hip_hit hit1, const hip_hit hit2);
extern int hipcfg_allowed_peers(const hip_hit hit1, const hip_hit hit2);
/* Get all pairs of peers allowed to comunicate with each other
* Return: the number of hit pairs returned if succeed
* 0 if no such hit pair
* -1 if error.
* Note: hits1 and hits2 are arrays with the at least max_cnt size, and have pre-alloced
* when calling this function.
*/
#define hipcfg_peers_allowed_fn "hipcfg_peers_allowed"
extern int (*hipcfg_peers_allowed_p)(hip_hit *hits1, hip_hit *hits2, int max_cnt);
extern int hipcfg_peers_allowed(hip_hit *hits1, hip_hit *hits2, int max_cnt);
/* Input: host - the legacy host IPv4/IPv6 address
* the sockaddr should point to a sockaddr_storage structure so that
* either an IPv4 or IPv6 address can be passed in. The sa_family must
* be set to AF_INET for an IPv4 address, or AF_INET6 for an IPv6 address.
* Output: eb - the endbox's LSI/HIT. sockaddr should point to a sockaddr_storage
* structure so that either an IPv4 or IPv6 address can be returned.
* When the call is returned, the sa_family is set to AF_INET if
* sockaddr_storage contains an IPv4 address, or AF_INET6 if it
* contains an IPv6 address.
* Return: 0 if the mapping found, a positive number if not found, -1 if error.
*
* Note: the old function is find_endbox2() which
* looking up file host_map.
*/
#define hipcfg_getEndboxByLegacyNode_fn "hipcfg_getEndboxByLegacyNode"
extern int (*hipcfg_getEndboxByLegacyNode_p)(const struct sockaddr *host, struct sockaddr *eb);
extern int hipcfg_getEndboxByLegacyNode(const struct sockaddr *host, struct sockaddr *eb);
/* Input: eb - endbox address either in IPv4 (LSI) or IPv6 (HIT)
* The sa_family must be set to ether AF_INET or AF_INET6
* before calling this function.
* Output: llip - lower layer IP address (e.g. BCWIN) in eihter IPv4/v6.
* sa_family will be set to either AF_INET or AF_INET6 after successfully
* calling this function per its actual IP address family.
* Return: 0 - if the lookup succeeed, 1 - if the mapping is not found, -1 if error.
*/
#define hipcfg_getLlipByEndbox_fn "hipcfg_getLlipByEndbox"
extern int (*hipcfg_getLlipByEndbox_p)(const struct sockaddr *eb, struct sockaddr *llip);
extern int hipcfg_getLlipByEndbox(const struct sockaddr *eb, struct sockaddr *llip);
/* Input eb - endbox address either in IPv4 (LSI) or IPv6 (HIT)
* The sa_family must be set to ether AF_INET or AF_INET6
* before calling this function.
* Output hosts - an array of legacy nodes. sa_family of each element
* will be set to either AF_INET or AF_INET6 per its actual IP address family
* The caller must provide the storage for the array.
* size - the size of array hosts (maximum number of elements can be returned).
* Return -1 if error, 0 if cannot find a match, a positivie number for the actual elements in hosts.
*/
#define hipcfg_getLegacyNodesByEndbox_fn "hipcfg_getLegacyNodesByEndbox"
extern int (*hipcfg_getLegacyNodesByEndbox_p)(const struct sockaddr *eb, struct sockaddr_storage *hosts, int size);
extern int hipcfg_getLegacyNodesByEndbox(const struct sockaddr *eb, struct sockaddr_storage *hosts, int size);
/* obtain the certificate that hold host identity (public key) in PEM format indexed by hit
* that is derived from the public key
* Input: hit - the hit in IPv6 notation string
* size - the buffer size
*
* Output: cert - a buffer that will hold certificate in PEM format
* Return -1 if error, 0 if succeeded
*/
#define hipcfg_verifyCert_fn "hipcfg_verifyCert"
extern int (*hipcfg_verifyCert_p)(const char *url, const hip_hit hit1);
extern int hipcfg_verifyCert(const char *url, const hip_hit hit1);
/* obtain the local certificate URL which is null terminated string
*
* Output: url - a buffer that will hold url certificate URL
* Input: size - the buffer size
* Return -1 if error, 0 if succeeded
*/
#define hipcfg_getLocalCertUrl_fn "hipcfg_getLocalCertUrl"
extern int (*hipcfg_getLocalCertUrl_p)(char *url, int size);
extern int hipcfg_getLocalCertUrl(char *url, int size);
/* Post the certificate that holds host identity (public key) in PEM format indexed by hit
* that is derived from the public key
* Input: hit - the hit in IPv6 notation string
* cert - a null terminated certificate in PEM format
* Return -1 if error, 0 if succeeded.
*/
#define hipcfg_postLocalCert_fn "hipcfg_postLocalCert"
extern int (*hipcfg_postLocalCert_p)(const char *hit);
extern int hipcfg_postLocalCert(const char *hit);
/* return a pointer to the local host identity struct */
#define hipcfg_getMyHostId_fn "hipcfg_getMyHostId"
extern hi_node *(*hipcfg_getMyHostId_p)();
extern hi_node *hipcfg_getMyHostId();
/* Get an array of configured known host peers.
return a positive number indicating the number of actual entries.
0 if there is no entries
-1 if error
Input:
peerNodes: an array of peer_node which will hold the configured peers
the memory must have been allocated before calling the function.
max_count: the size of the peerNodes array
*/
#define hipcfg_getPeerNodes_fn "hipcfg_getPeerNodes"
extern int (*hipcfg_getPeerNodes_p)(struct peer_node *peerNodes, int max_count);
extern int hipcfg_getPeerNodes(struct peer_node *peerNodes, int max_count);
#endif

View File

@ -0,0 +1,66 @@
#ifndef _HIPSPD_LDAP_H_
#define _HIPSPD_LDAP_H_
#include <openssl/ssl.h>
#include <openssl/engine.h>
#include <hip/hip_cfg.h>
#include "LDAPConnection.h"
#include "hip_types.h"
class hipCfgLdap : public hipCfg
{
public:
int loadCfg(struct hip_conf *hc);
int getLocalCertUrl(char *url, int size);
int postLocalCert(const char *hit);
int verifyCert(const char *url, const hip_hit hit);
hi_node *getMyHostId(){ return _hostid;};
int getPeerNodes(struct peer_node *peerNodes, int max_count);
static hipCfgLdap *getInstance();
private:
hipCfgLdap();
int connectToLdap();
void disconnectLdap();
int getCertFromLdap(const char *url, char *buf, int size);
int getCertFromSc(char *buf, int size);
int connect_card(struct sc_context *ctx, struct sc_card **cardp,
int reader_id, int slot_id, int wait);
int verify_pin(struct sc_pkcs15_card *p15card, const char *pincode);
int read_sc_cert(struct sc_pkcs15_card *p15card, u8 *out_buf, int len);
int init_ssl_context();
int hi_to_hit(hi_node *hi, hip_hit hit);
int khi_hi_input(hi_node *hi, __u8 *out);
int bn2bin_safe(const BIGNUM *a, unsigned char *to, int len);
int khi_encode_n(__u8 *in, int len, __u8 *out, int n);
ENGINE *engine_init(const char *pin);
int load_engine_fn(ENGINE *e, const char *engine_id,
const char **pre_cmds, int pre_num,
const char **post_cmds, int post_num);
void engine_teardown(ENGINE *e);
SSL_CTX *ssl_ctx_init(ENGINE *e, const char *pin);
int mkHIfromSc();
int mkHIfromPkey(RSA *rsa, DSA *dsa, hi_node *hostid);
int getEndboxMapsFromLdap();
int getEndboxMapsFromLocalFile();
int getPeerAllowedFromLdap();
int verify_certificate(X509 *cert);
static int callb(int rc, X509_STORE_CTX *ctx);
private:
map <string, struct peer_node *> _hit_to_peers; /* configured peers indexed by hit string */
string _basedn;
static LDAPConnection *_lc;
static hipCfgLdap *_instance;
string _scPrivKeyID;
string _scPin;
string _scCert;
hi_node *_hostid;
SSL *_ssl;
X509_STORE *_store;
RSA *_rsa;
DSA *_dsa;
struct hip_conf *_hcfg;
};
#endif

68
src/include/hip/hip_dns.h Normal file
View File

@ -0,0 +1,68 @@
/*
* Host Identity Protocol
* Copyright (C) 2006 the Boeing Company
*
* 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 2 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.
*
* dns.h
*
* Authors: Jeff Ahrenholz <jeffrey.m.ahrenholz@boeing.com>
*
* Definitions for DNS headers.
*
*/
#ifndef _HIP_DNS_H_
#define _HIP_DNS_H_
/* DNS packet structures */
struct dns_hdr {
__u16 transaction_id;
__u16 flags;
__u16 question_count;
__u16 answer_count;
__u16 namesrvr_count;
__u16 additional_count;
#ifdef __WIN32__
};
#else
} __attribute__ ((packed));
#endif
#define HIP_RR_TYPE 55
#define HIP_RR_PKALG_DSA 1
#define HIP_RR_PKALG_RSA 2
#define DNS_FLAG_MASK_STDQUERY 0x0001
#define DNS_FLAG_AUTHORITATIVE 0x0400
#define DNS_FLAG_ANSWER 0x8000
#define DNS_FLAG_NXDOMAIN 0x03
#define DNS_QTYPE_CLASS_IN 1
#define DNS_DEFAULT_TTL 3600
#ifndef DNS_TYPE_A /* also defined in WinDNS.h */
#define DNS_TYPE_A 1
#define DNS_TYPE_PTR 12
#endif
#define DNS_TYPE_NXDOMAIN -1 /* (not a real DNS answer type) */
struct dns_ans_hdr {
__u16 ans_name;
__u16 ans_type;
__u16 ans_class;
__u32 ans_ttl;
__u16 ans_len;
#ifdef __WIN32__
};
#else
} __attribute__ ((packed));
#endif
#endif /* _HIP_DNS_H_ */

379
src/include/hip/hip_funcs.h Normal file
View File

@ -0,0 +1,379 @@
/*
* Host Identity Protocol
* Copyright (C) 2002-05 the Boeing Company
*
* 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 2 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.
*
* Definitions for the HIP protocol.
*
* Version: @(#)hip.h 1.5 08/12/04
*
* Authors: Jeff Ahrenholz, <jeffrey.m.ahrenholz@boeing.com>
* Tom Henderson, <thomas.r.henderson@boeing.com>
*
*
*/
#ifndef _HIP_FUNCS_H_
#define _HIP_FUNCS_H_
/* XXX clean up type portability */
#if defined (__MACOSX__)
#include <mac/mac_types.h>
#elif defined (__WIN32__)
#include <win32/types.h>
#else /* Linux */
#include <asm/types.h>
#endif
#ifdef __MACOSX__
#include <sys/types.h>
#include <sys/time.h>
#endif
#ifdef __WIN32__
#include <winsock2.h>
#else
#include <sys/socket.h> /* sockaddr */
#include <netinet/in.h>
#endif
#include <sys/types.h>
#include <openssl/bn.h>
#include <openssl/hmac.h>
#include <openssl/rsa.h>
#include <time.h>
/*
* Macros
*/
/* LSI functions */
#define IS_LSI32(a) ((a & 0xFF) == 0x01)
#ifdef __WIN32__
#define IN6_ARE_ADDR_EQUAL IN6_ADDR_EQUAL
#define IS_HIT(x) (( (ntohs(((struct in6_addr*)x)->s6_words[0]) & 0xFFFF) \
== ((HIT_PREFIX_SHA1_32BITS >> 4) & 0xFFFF)) && \
( (ntohs(((struct in6_addr*)x)->s6_words[1]) & 0xFFF0) \
== ((HIT_PREFIX_SHA1_32BITS & 0xFFFF)) ) )
#elif defined (__MACOSX__)
#define IS_HIT(x) ( (ntohl(((struct in6_addr*)x)->__u6_addr.__u6_addr32[0]) \
& 0xFFFFFFF0L) == HIT_PREFIX_SHA1_32BITS )
#else /* Linux */
#define IS_HIT(x) ( (ntohl(((struct in6_addr*)x)->s6_addr32[0]) & 0xFFFFFFF0L) \
== HIT_PREFIX_SHA1_32BITS )
#endif
#define SA2IP6(x) ( &((struct sockaddr_in6*)x)->sin6_addr )
#if defined(__MACOSX__) && defined(__BIG_ENDIAN__)
#define IS_LSI(a) ( ( ((struct sockaddr*)a)->sa_family == AF_INET) ? \
(IS_LSI32( ((struct sockaddr_in*)a)->sin_addr.s_addr >> 24)) : \
(IS_HIT( &((struct sockaddr_in6*)a)->sin6_addr) ) )
#else /* __MACOSX__ */
#define IS_LSI(a) ( (((struct sockaddr*)a)->sa_family == AF_INET) ? \
(IS_LSI32(((struct sockaddr_in*)a)->sin_addr.s_addr)) : \
(IS_HIT( &((struct sockaddr_in6*)a)->sin6_addr) ) )
#endif /* __MACOSX__ */
#define VALID_FAM(a) ( (((struct sockaddr*)a)->sa_family == AF_INET) || \
(((struct sockaddr*)a)->sa_family == AF_INET6) )
#define IN_LOOP(a) \
(htonl(((struct sockaddr_in*)a)->sin_addr.s_addr) >> IN_CLASSA_NSHIFT \
== (INADDR_LOOPBACK >> IN_CLASSA_NSHIFT))
#define IN6_LOOP(a) \
IN6_IS_ADDR_LOOPBACK( &((struct sockaddr_in6*)a)->sin6_addr )
/*
* Function prototypes
*/
/* hip_output.c */
int hip_send_I1(hip_hit* hit, hip_assoc *hip_a, int pos);
int hip_send_R1(struct sockaddr *src, struct sockaddr *dst, hip_hit *hiti,
hi_node *hi, __u16 dst_port, int use_udp);
int hip_generate_R1(__u8 *data, hi_node *hi, hipcookie *cookie,
dh_cache_entry *dh_entry);
int hip_send_I2(hip_assoc *hip_a);
int hip_send_R2(hip_assoc *hip_a);
int hip_send_update(hip_assoc *hip_a, struct sockaddr *newaddr,
struct sockaddr *dstaddr, int use_udp);
int hip_send_update_proxy_ticket(hip_assoc *hip_mr, hip_assoc *hip_a,
int use_udp);
int hip_send_close(hip_assoc *hip_a, int send_ack);
int hip_send_notify(hip_assoc *hip_a, int code, __u8 *data, int data_len);
int hip_send(__u8 *data, int len, struct sockaddr *src, struct sockaddr *dst,
hip_assoc *hip_a, int retransmit, __u16 dst_port,
int use_udp);
int hip_retransmit(hip_assoc *hip_a, __u8 *data, int len, struct sockaddr *src,
struct sockaddr *dst);
#ifdef __WIN32__
void udp_hip_keepalive (void *arg);
#else
void *udp_hip_keepalive (void *arg);
#endif
int build_tlv_hostid_len(hi_node *hi, int use_hi_name);
int build_tlv_hostid(__u8 *data, hi_node *hi, int use_hi_name);
int build_tlv_reg_info(__u8 *data, int location);
int build_tlv_reg_req(__u8 *data, int location, struct reg_entry *reg_offered);
int build_tlv_reg_resp(__u8 *data, int location,
struct reg_entry *reg_requested);
int build_tlv_reg_failed(__u8 *data, int location,
struct reg_entry *reg_requested);
int build_rekey(hip_assoc *hip_a);
int build_tlv_cert(__u8 *buff);
/* hip_input.c */
int hip_parse_hdr(__u8 *data, int len, struct sockaddr *src,
struct sockaddr *dst, __u16 family, hiphdr **hdr, int use_udp);
int hip_handle_I1(__u8 *data, hip_assoc *hip_a, struct sockaddr *src,
struct sockaddr *dst, __u16 *dst_port, int use_udp);
int hip_handle_R1(__u8 *data, hip_assoc *hip_a, struct sockaddr *src,
__u16 *dst_port, int use_udp);
int hip_handle_I2(__u8 *data, hip_assoc *hip_a, struct sockaddr *src,
struct sockaddr *dst, __u16 *dst_port, int use_udp);
int hip_handle_R2(__u8 *data, hip_assoc *hip_a, __u16 *dst_port, int use_udp);
int hip_handle_update(__u8 *data, hip_assoc *hip_a, struct sockaddr *src, __u16 *dst_port, int use_udp);
int hip_handle_close(__u8 *data, hip_assoc *hip_a, __u16 *dst_port, int use_udp);
int hip_handle_notify(__u8 *buff, hip_assoc *hip_a, __u16 *dst_port, int use_udp);
int hip_finish_rekey(hip_assoc *hip_a, int rebuild, int use_udp);
int hip_handle_BOS(__u8 *data, struct sockaddr *src);
int hip_handle_CER(__u8 *data, hip_assoc *hip_a);
int rebuild_sa(hip_assoc *hip_a, struct sockaddr *newaddr, __u32 newspi,
int in, int peer, int use_udp);
void handle_reg_info();
void handle_reg_request(char *data, int location);
/* hip_ipsec.c */
__u32 get_next_spi(hip_assoc *hip_a);
int sadb_add(struct sockaddr *src, struct sockaddr *dst, struct sockaddr *inner_src,
struct sockaddr *inner_dst, hip_assoc *hip_a, __u32 spi, int direction);
/*int sadb_add(struct sockaddr *src, struct sockaddr *dst, hip_assoc *hip_a,
__u32 spi, int direction);*/
int sadb_readdress(struct sockaddr *src, struct sockaddr *dst, hip_assoc *hip_a,
__u32 spi);
int sadb_add_policy(hip_assoc *hip_a, struct sockaddr *out_src, struct sockaddr *out_dst,
struct sockaddr *in_src, struct sockaddr *in_dst, int direction);
/*int sadb_add_policy(struct sockaddr *src, struct sockaddr *dst, int direction);*/
int sadb_delete(hip_assoc *hip_a, struct sockaddr *src, struct sockaddr *dst, __u32 spi);
int sadb_delete_policy(struct sockaddr *src,struct sockaddr *dst,int direction);
int sadb_register(int satype);
int check_last_used(hip_assoc *hip_a, int direction, struct timeval *now);
int sadb_lsi(struct sockaddr *ip, struct sockaddr *lsi4, struct sockaddr *lsi6);
int delete_associations(hip_assoc *hip_a, __u32 old_spi_in, __u32 old_spi_out);
int flush_hip_associations();
int parse_acquire(char *data, struct sockaddr *src, struct sockaddr *dst);
int parse_expire(char *data, __u32 *spi);
void pfkey_packet_type(int type, char *r);
void hip_handle_pfkey(char *buff);
void hip_check_pfkey_buffer();
void update_lsi_mapping(struct sockaddr *dst, struct sockaddr *lsi,hip_hit hit);
/* hip_keymat.c */
int set_secret_key(unsigned char *key, hip_assoc *hip_a);
unsigned char *get_key(hip_assoc *hip_a, int type, int peer);
void compute_keys(hip_assoc *hip_a);
int compute_keymat(hip_assoc *hip_a);
int draw_keys(hip_assoc *hip_a, int draw_hip_keys, int keymat_index);
int draw_mr_key(hip_assoc *hip_a, int keymat_index);
int auth_key_len(int suite_id);
int enc_key_len(int suite_id);
int enc_iv_len(int suite_id);
/* hip_util.c */
int add_addresses_from_dns(char *name, hi_node *hi);
RSA *hip_rsa_new();
void hip_rsa_free(RSA *rsa);
DSA *hip_dsa_new();
void hip_dsa_free(DSA *dsa);
int save_identities_file(int);
int read_conf_file(char *);
int read_reg_file(void);
__u16 conf_transforms_to_mask();
hi_node *create_new_hi_node();
void append_hi_node(hi_node **head, hi_node *append);
int add_peer_hit(hip_hit peer_hit, struct sockaddr *peer_addr);
hi_node *find_host_identity(hi_node* hi_head, const hip_hit hitr);
int key_data_to_hi(const __u8 *data, __u8 alg, int hi_length, __u8 di_type,
int di_length, hi_node **hi_p, int max_length);
hi_node *get_preferred_hi(hi_node *node);
int get_addr_from_list(sockaddr_list *list, int family,
struct sockaddr *addr);
hip_assoc *init_hip_assoc(hi_node *my_host_id, const hip_hit *peer_hit);
void replace_hip_assoc(hip_assoc *a_old, hip_assoc *a_new);
int free_hip_assoc(hip_assoc *hip_a);
void free_hi_node(hi_node *hi);
void clear_retransmissions(hip_assoc *hip_a);
void set_state(hip_assoc *hip_a, int state);
hip_hit *hit_lookup(struct sockaddr*);
hi_node *lsi_lookup(struct sockaddr *lsi);
__u32 lsi_name_lookup(char *name, int name_len);
struct sockaddr *get_hip_dns_server();
__u32 receive_hip_dns_response(unsigned char *buff, int len);
int hits_equal(const hip_hit hit1, const hip_hit hit2);
void hit_to_sockaddr (struct sockaddr_in6 *sockad, hip_hit hit);
void print_cookie(hipcookie *cookie);
int str_to_addr(__u8 *data, struct sockaddr *addr);
int hit2hitstr(char *hit_str, const hip_hit hit);
int addr_to_str(struct sockaddr *addr, __u8 *data, int len);
int hex_to_bin(char *src, char *dst, int dst_len);
int solve_puzzle(hipcookie *cookie, __u64 *solution,
hip_hit *hit_i, hip_hit *hit_r);
int validate_solution(const hipcookie *cookie_r, const hipcookie *cookie_i,
hip_hit *hit_i, hip_hit *hit_r, __u64 solution);
int hi_to_hit(hi_node *hi, hip_hit hit);
int validate_hit(hip_hit hit, hi_node *hi);
void print_hex(const void *data, int len);
void print_binary(void *data, int len);
int compare_bits(const char *s1, int s1_len, const char *s2, int s2_len,
int numbits);
int compare_hits(hip_hit a, hip_hit b);
int compare_hits2(void const *s1, void const *s2);
int maxof(int num_args, ...);
int hip_header_offset(const __u8 *data);
int udp_header_offset(const __u8 *data);
__u16 checksum_udp_packet(__u8 *data, struct sockaddr *src, struct sockaddr *dst);
void hip_packet_type(int type, char *r);
void print_usage(void);
__u16 checksum_packet(__u8 *data, struct sockaddr *src, struct sockaddr *dst);
__u16 checksum_magic(const hip_hit *i, const hip_hit *r);
int tlv_length_to_parameter_length(int length);
int eight_byte_align(int length);
hip_assoc* find_hip_association(struct sockaddr *src, struct sockaddr *dst,
hiphdr* hiph);
hip_assoc* find_hip_association2(hiphdr* hiph);
hip_assoc* find_hip_association3(struct sockaddr *src, struct sockaddr *dst);
hip_assoc* find_hip_association4(hip_hit hit);
void * binsert(const void *ky, const void *bs, size_t nel, size_t width, int (*compar)(const void *, const void *));
void log_registration(hip_reg *hip_r, int a);
void print_reg_table(hip_reg *hip_r);
int delete_reg_table(hip_reg key, hip_reg *hip_r);
int insert_reg_table(hip_reg key, hip_reg *hip_r);
returned *search_reg_table(hip_reg p, hip_reg *hip_r, returned *ret);
void cb(int p, int n, void *arg);
void init_crypto();
void deinit_crypto();
void pthread_locking_callback(int mode, int type, char *file, int line);
int init_log();
void fflush_log();
void log_(int level, char *fmt, ...);
char *logaddr(struct sockaddr *addr);
void logdsa(DSA *dsa);
void logrsa(RSA *rsa);
void logdh(DH *dh);
void logbn(BIGNUM *bn);
int bn2bin_safe(const BIGNUM *a, unsigned char *to, int len);
void log_hipa_fromto(int level, char *msg, hip_assoc *hip_a,__u8 from,__u8 to);
void log_hipopts();
#ifdef __WIN32__
void log_WinError(int code);
#endif
#ifdef __UMH__
int do_bcast();
#endif
void hip_sleep(int seconds);
void hip_writelock();
void hip_exit(int signal);
hip_mr_client *init_hip_mr_client(hip_hit *peer_hit, struct sockaddr *src);
int free_hip_mr_client(hip_mr_client *hip_mr_c);
int add_proxy_ticket(tlv_proxy_ticket *ticket);
/* hip_xml.c */
int locate_config_file(char *filename, int filename_size, char *default_name);
int read_identities_file(char *filename, int mine);
#ifdef SMA_CRAWLER
int read_peer_identities_from_hipcfg();
#endif /* SMA_CRAWLER */
void print_hi_to_buff(uint8_t **bufp, int *buf_len, hi_node *hi, int mine);
int save_identities_file(int);
int read_conf_file(char *);
/* hip_netlink.c */
int hip_netlink_open();
int get_my_addresses();
int select_preferred_address();
int is_my_address(struct sockaddr *addr);
int hip_handle_netlink(char *data, int length);
int add_address_to_iface(struct sockaddr *addr, int plen, int if_index);
int devname_to_index(char *dev, __u64 *mac);
sockaddr_list *add_address_to_list(sockaddr_list **list, struct sockaddr *addr,
int ifi);
void delete_address_from_list(sockaddr_list **list, struct sockaddr *addr,
int ifi);
void delete_address_entry_from_list(sockaddr_list **list, sockaddr_list *entry);
void make_address_active(sockaddr_list *item);
int update_peer_list_address(const hip_hit peer_hit, struct sockaddr *old_addr, struct sockaddr *new_addr);
/* hip_cache.c */
void init_all_R1_caches();
void init_R1_cache(hi_node *hi);
hipcookie *generate_cookie();
void replace_next_R1();
int compute_R1_cache_index(hip_hit *hiti, __u8 current);
int calculate_r1_length(hi_node *hi);
void init_dh_cache();
dh_cache_entry *new_dh_cache_entry(__u8 group_id);
dh_cache_entry *get_dh_entry(__u8 group_id, int new);
void unuse_dh_entry(DH *dh);
void expire_old_dh_entries();
/* hip_status.c */
int hip_status_open();
void hip_handle_status_request(__u8 *buff, int len, struct sockaddr *addr);
/* hip_dht.c */
int hip_dht_lookup_hit(struct sockaddr *lsi, hip_hit *hit, int retry);
int hip_dht_lookup_address(hip_hit *hit, struct sockaddr *addr, int retry);
int hip_dht_publish(hip_hit *hit, struct sockaddr *addr, int retry);
int hip_dht_select_server(struct sockaddr *addr);
int add_addresses_from_dht(hi_node *hi, int retry);
void publish_my_hits();
/*
* Miscellaneous
*/
static __inline __u64 __hton64( __u64 i )
{
#if defined(__MACOSX__) && defined(__BIG_ENDIAN__)
return i;
#endif
return ((__u64)(htonl((__u32)(i) & 0xffffffff)) << 32)
| htonl((__u32)(((i) >> 32) & 0xffffffff ));
}
#define hton64(i) __hton64( i )
#define ntoh64(i) __hton64( i )
/* Unix replacements */
#ifdef __WIN32__
static __inline int gettimeofday(struct timeval *tv, void *tz)
{
if (!tv) return(-1);
tv->tv_usec = 0;
tv->tv_sec = time(NULL);
return(0);
}
#define pthread_mutex_lock(mp) WaitForSingleObject(*mp, INFINITE)
#define pthread_mutex_unlock(mp) ReleaseMutex(*mp)
#define pthread_mutex_init(mp, mattr) *mp = CreateMutex(NULL, FALSE, NULL)
#define pthread_mutex_destroy(mp) CloseHandle(*mp)
#define snprintf _snprintf
#else
#define closesocket close
#endif /* __WIN32__ */
#endif

View File

@ -0,0 +1,123 @@
/*
* Host Identity Protocol
* Copyright (C) 2002-05 the Boeing Company
*
* 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 2 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.
*
* hip_globals.h
*
* Author: Jeff Ahrenholz, <jeffrey.m.ahrenholz@boeing.com>
*
*/
#include <openssl/dsa.h> /* DSA support */
#include <openssl/dh.h> /* Diffie-Hellman contexts */
#include <math.h> /* for exponential macros (reg life) */
#include <hip/hip_types.h>
#include <hip/hip_stun.h>
/* global variables */
/* Registration global variables */
extern long int num_entries; /* number of entries to store in the registration table when -g option is activated (used in rvs mode) */
extern int min_life; /* to store info from rvs (used in normal mode) */
extern int max_life;
extern int reg_type;
extern int add_reg_info; /* to add the parameter (used in rvs mode) */
extern int add_reg_request; /* (used in normal mode) */
extern int add_reg_response; /* (used in rvs mode) */
extern int add_reg_failed; /* (used in rvs mode) */
extern int resp_lifetime; /* values received from a reg_response parameter (used in rvs mode) */
extern int resp_reg_type;
extern int fail_type; /* values received from a reg_failed parameter (used in rvs mode) */
extern int fail_reg_type;
extern int repeat_reg; /* in case we need to update the registration (used in normal mode) */
extern int repeat_type;
extern int need_to_send_update2;
/* Relaying global variables (used only in rvs mode) */
extern from fr;
extern via fr2;
extern int no_R1;
/* Array storing HIP association structs (this is the state machine state) */
extern hip_assoc hip_assoc_table[MAX_CONNECTIONS];
extern int max_hip_assoc;
extern const hip_hit zero_hit;
/* Array storing Mobile router clients */
extern hip_mr_client hip_mr_client_table[MAX_MR_CLIENTS];
extern int max_hip_mr_clients;
extern int external_if_index;
extern int new_external_address;
extern hip_hit mobile_router_hit;
extern hip_mutex_t hip_mr_client_mutex;
/* Array storing HIP registrations structs */
extern hip_reg hip_reg_table[MAX_REGISTRATIONS];
extern long int num_hip_reg;
/* Linked list of my host identities */
extern hi_node *my_hi_head;
/* Linked list of my addresses */
extern sockaddr_list *my_addr_head;
/* Linked list of peer host identities */
extern hi_node *peer_hi_head;
/* Linked list of Diffie-Hellman contexts */
extern dh_cache_entry *dh_cache;
/* Diffie-Hellman constants */
extern const unsigned char *dhprime[DH_MAX];
extern const int dhprime_len[DH_MAX]; /* only used by new_dh_cache_entry()
use DH_size() elsewhere */
extern unsigned char dhgen[DH_MAX];
extern int pfk_seqno; /* PFKEY messages need to be numbered */
extern int s_hip, s_pfk; /* PFKEY and RAW socket handles */
extern int s_hip_udp; /* socket for UDP-encapsulated HIP packets */
#undef s_net
extern int s_net; /* netlink socket */
extern int s6_hip; /* RAW IPv6 socket handle */
extern int s_stat; /* status socket */
extern int is_behind_nat; /* determined with STUN : indicates whether the host is behind a NAT or not */
extern StunAddress4 STUN_server_addr;
/* Global options */
extern struct hip_opt OPT;
/* Global configuration data */
extern struct hip_conf HCNF;
#ifdef __UMH__
extern int pfkeysp[2];
extern int g_state;
#endif
#ifdef __CYGWIN__
extern int netlsp[2];
#endif
#ifdef __WIN32__
extern int netlsp[2];
#endif
const unsigned char khi_context_id[16];
/* smartcard signing */
extern RSA *sc_rsa;
extern DSA *sc_dsa;

270
src/include/hip/hip_proto.h Normal file
View File

@ -0,0 +1,270 @@
/*
* Host Identity Protocol
* Copyright (C) 2002-06 the Boeing Company
*
* 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 2 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.
*
* Definitions for the HIP protocol.
*
* Version: @(#)hip.h 1.5 08/12/04
*
* Authors: Jeff Ahrenholz, <jeffrey.m.ahrenholz@boeing.com>
* Tom Henderson, <thomas.r.henderson@boeing.com>
*
*
*/
#ifndef _HIP_PROTOCOL_H_
#define _HIP_PROTOCOL_H_
#include <openssl/bn.h>
#include <openssl/hmac.h>
#include <openssl/rsa.h>
/*
* Protocol constants
*/
#define H_PROTO_UDP 17
#define HIP_ESP_UDP_PORT 54500
#define HIP_PROTO_VER 1
#define H_PROTO_HIP 139 /* IP layer protocol number for private encryption */
#define HIP_PAYLOAD_PROTOCOL 59
#define STATUS_PORT 4051 /* UDP port for obtaining status data */
#define SPI_RESERVED 255
#define HIP_ALIGN 4
#define ACCEPTABLE_R1_COUNT_RANGE 2
#define HIT_SIZE 16
#define HIT_PREFIX_TYPE1_SHA1 0x40
typedef enum {
UNASSOCIATED, /* State machine start */
I1_SENT, /* Initiating HIP */
I2_SENT, /* Waiting to finish HIP */
R2_SENT, /* Waiting to finish HIP */
ESTABLISHED, /* HIP SA established */
REKEYING, /* HIP SA established, rekeying */
CLOSING, /* HIP SA closing, no data can be sent */
CLOSED, /* HIP SA closed, no data can be sent */
E_FAILED /* HIP SA establishment failed */
} HIP_STATES;
/* HIP packet types */
typedef enum {
HIP_I1=1,
HIP_R1,
HIP_I2,
HIP_R2,
CER, /* 5 - removed from draft-ietf-hip-base-03 */
BOS=11, /* 11 - removed from draft-ietf-hip-base-01 */
UPDATE=16, /* 16 */
NOTIFY=17, /* 17 */
CLOSE=18, /* 18 */
CLOSE_ACK=19, /* 19 */
} HIP_PACKETS;
/* HIP controls */
typedef enum {
CTL_ANON = 0x0001,
} HIP_CONTROLS;
/* HIP TLV parameters */
#define PARAM_ESP_INFO 65
#define PARAM_R1_COUNTER 128
#define PARAM_LOCATOR 193
#define PARAM_PUZZLE 257
#define PARAM_SOLUTION 321
#define PARAM_SEQ 385
#define PARAM_ACK 449
#define PARAM_DIFFIE_HELLMAN 513
#define PARAM_HIP_TRANSFORM 577
#define PARAM_ENCRYPTED 641
#define PARAM_HOST_ID 705
#define PARAM_CERT 768
#define PARAM_PROXY_TICKET 812
#define PARAM_AUTH_TICKET 822
#define PARAM_NOTIFY 832
#define PARAM_ECHO_REQUEST 897
#define PARAM_REG_INFO 930
#define PARAM_REG_REQUEST 932
#define PARAM_REG_RESPONSE 934
#define PARAM_REG_FAILED 936
#define PARAM_REG_REQUIRED /* TBD */
#define PARAM_ECHO_RESPONSE 961
#define PARAM_ESP_TRANSFORM 4095
#define PARAM_TRANSFORM_LOW 2048 /* defines range for transforms */
#define PARAM_TRANSFORM_HIGH 4095
#define PARAM_HMAC 61505
#define PARAM_HMAC_2 61569
#define PARAM_HIP_SIGNATURE_2 61633
#define PARAM_HIP_SIGNATURE 61697
#define PARAM_ESP_INFO_NOSIG 62565
#define PARAM_ECHO_REQUEST_NOSIG 63661
#define PARAM_ECHO_RESPONSE_NOSIG 63425
#define PARAM_FROM 65498
#define PARAM_RVS_HMAC 65500
#define PARAM_VIA_RVS 65502
#define PARAM_CRITICAL_BIT 0x0001
/* encryption algorithms */
typedef enum {
RESERVED, /* 0 */
ESP_AES_CBC_HMAC_SHA1, /* 1 */
ESP_3DES_CBC_HMAC_SHA1, /* 2 */
ESP_3DES_CBC_HMAC_MD5, /* 3 */
ESP_BLOWFISH_CBC_HMAC_SHA1, /* 4 */
ESP_NULL_HMAC_SHA1, /* 5 */
ESP_NULL_HMAC_MD5, /* 6 */
SUITE_ID_MAX, /* 7 */
} SUITE_IDS;
#define ENCR_NULL(a) ((a==ESP_NULL_HMAC_SHA1) || \
(a==ESP_NULL_HMAC_MD5))
/* Supported transforms are compressed into a bitmask... */
/* Default HIP transforms proposed when none are specified in config */
#define DEFAULT_HIP_TRANS \
((1 << ESP_AES_CBC_HMAC_SHA1) | \
(1 << ESP_3DES_CBC_HMAC_SHA1) | \
(1 << ESP_3DES_CBC_HMAC_MD5) | \
(1 << ESP_BLOWFISH_CBC_HMAC_SHA1) | \
(1 << ESP_NULL_HMAC_SHA1) | \
(1 << ESP_NULL_HMAC_MD5))
/* Default ESP transforms proposed when none are specified in config */
#define ESP_OFFSET 8
#ifndef __CYGWIN__
#define DEFAULT_ESP_TRANS \
((1 << (ESP_OFFSET + ESP_AES_CBC_HMAC_SHA1)) | \
(1 << (ESP_OFFSET + ESP_3DES_CBC_HMAC_SHA1)) | \
(1 << (ESP_OFFSET + ESP_3DES_CBC_HMAC_MD5)) | \
(1 << (ESP_OFFSET + ESP_BLOWFISH_CBC_HMAC_SHA1)) | \
(1 << (ESP_OFFSET + ESP_NULL_HMAC_SHA1)) | \
(1 << (ESP_OFFSET + ESP_NULL_HMAC_MD5)))
#else /* Windows transform support more limited. */
#define DEFAULT_ESP_TRANS \
((1 << (ESP_OFFSET + ESP_3DES_CBC_HMAC_SHA1)) | \
(1 << (ESP_OFFSET + ESP_3DES_CBC_HMAC_MD5)) | \
(1 << (ESP_OFFSET + ESP_NULL_HMAC_SHA1)) | \
(1 << (ESP_OFFSET + ESP_NULL_HMAC_MD5)))
#endif
/* HI (signature) algorithms */
enum {
HI_ALG_RESERVED,
HI_ALG_DSA = 3,
HI_ALG_RSA = 5,
} HI_ALGORITHMS;
#define HIP_RSA_DFT_EXP RSA_F4 /* 0x10001L = 65537; 3 and 17 are also common */
#define HI_TYPESTR(a) ((a==HI_ALG_DSA) ? "DSA" : \
(a==HI_ALG_RSA) ? "RSA" : "UNKNOWN")
/* HI Domain Identifier types */
enum {
DIT_NONE, /* none included */
DIT_FQDN, /* Fully Qualified Domain Name, in binary format */
DIT_NAI, /* Network Access Identifier, binary, login@FQDN */
} HI_DIT;
typedef enum {
UNVERIFIED,
ACTIVE,
DEPRECATED,
DELETED, /* not in spec, but used when address is removed */
} ADDRESS_STATES;
typedef enum {
HIP_ENCRYPTION,
HIP_INTEGRITY,
ESP_ENCRYPTION,
ESP_AUTH,
} KEY_TYPES;
typedef enum {
GL_HIP_ENCRYPTION_KEY, /* 0 */
GL_HIP_INTEGRITY_KEY,
LG_HIP_ENCRYPTION_KEY,
LG_HIP_INTEGRITY_KEY,
GL_ESP_ENCRYPTION_KEY,
GL_ESP_AUTH_KEY,
LG_ESP_ENCRYPTION_KEY,
LG_ESP_AUTH_KEY /* 7 */
} HIP_KEYMAT_KEYS;
typedef enum {
KEY_LEN_NULL = 0, /* RFC 2410 */
KEY_LEN_MD5 = 16, /* 128 bits per RFC 2403 */
KEY_LEN_SHA1 = 20, /* 160 bits per RFC 2404 */
KEY_LEN_3DES = 24, /* 192 bits (3x64-bit keys) RFC 2451 */
KEY_LEN_AES = 16, /* 128 bits per RFC 3686; also 192, 256-bits */
KEY_LEN_BLOWFISH = 16, /* 128 bits per RFC 2451 */
} HIP_KEYLENS;
/* Diffie-Hellman Group IDs */
typedef enum {
DH_RESERVED,
DH_384,
DH_OAKLEY_1,
DH_MODP_1536,
DH_MODP_3072,
DH_MODP_6144,
DH_MODP_8192,
DH_MAX
} DH_GROUP_IDS;
/* choose default DH group here */
#define DEFAULT_DH_GROUP_ID DH_MODP_1536
#define DH_MAX_LEN 1024
/*
* HIP LOCATOR parameters
*/
#define LOCATOR_PREFERRED 0x01
#define LOCATOR_TRAFFIC_TYPE_BOTH 0x00
#define LOCATOR_TRAFFIC_TYPE_SIGNALING 0x01
#define LOCATOR_TRAFFIC_TYPE_DATA 0x02
#define LOCATOR_TYPE_IPV6 0x00
#define LOCATOR_TYPE_SPI_IPV6 0x01
/*
* Notify error types
*/
#define NOTIFY_UNSUPPORTED_CRITICAL_PARAMETER_TYPE 1
#define NOTIFY_INVALID_SYNTAX 7
#define NOTIFY_NO_DH_PROPOSAL_CHOSEN 14
#define NOTIFY_INVALID_DH_CHOSEN 15
#define NOTIFY_NO_HIP_PROPOSAL_CHOSEN 16
#define NOTIFY_INVALID_HIP_TRANSFORM_CHOSEN 17
#define NOTIFY_NO_ESP_PROPOSAL_CHOSEN 18
#define NOTIFY_INVALID_ESP_TRANSFORM_CHOSEN 19
#define NOTIFY_AUTHENTICATION_FAILED 24
#define NOTIFY_CHECKSUM_FAILED 26
#define NOTIFY_HMAC_FAILED 28
#define NOTIFY_ENCRYPTION_FAILED 32
#define NOTIFY_INVALID_HIT 40
#define NOTIFY_BLOCKED_BY_POLICY 42
#define NOTIFY_SERVER_BUSY_PLEASE_RETRY 44
#define NOTIFY_LOCATOR_TYPE_UNSUPPORTED 46
#define NOTIFY_I2_ACKNOWLEDGEMENT 16384
/*
* Registration types
*/
#define REG_RVS 1
#define REG_MR 2
#endif /* !_HIP_PROTOCOL_H_ */

152
src/include/hip/hip_sadb.h Normal file
View File

@ -0,0 +1,152 @@
/*
* Host Identity Protocol
* Copyright (C) 2002-04 the Boeing Company
*
* 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 2 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.
*
* hip_sadb.h
*
* Authors: Jeff Ahrenholz <jeffrey.m.ahrenholz@boeing.com>
*
* the HIP Security Association database
*
*/
#ifdef __MACOSX__
#include <sys/types.h>
#include <mac/mac_types.h>
#else
#ifdef __WIN32__
#include <win32/types.h>
#else
#include <asm/types.h> /* __u16, __u32, etc */
#endif /* __WIN32__ */
#endif
#include <sys/types.h> /* for socket.h */
#ifdef __WIN32__
#include <winsock2.h>
#include <ws2tcpip.h>
#else
#include <sys/socket.h> /* struct sockaddr */
#include <netinet/in.h> /* struct sockaddr_in */
#endif /* __WIN32__ */
#include <openssl/des.h> /* des_key_schedule */
#include <openssl/aes.h> /* aes_key */
#include <openssl/blowfish.h> /* bf_key */
/*
* definitions
*/
#define SADB_SIZE 512
#define LSI4(a) (((struct sockaddr_in*)a)->sin_addr.s_addr)
/* HIP Security Association entry */
typedef struct _hip_sadb_entry
{
struct _hip_sadb_entry *next;
__u32 spi; /* primary index into SADB */
__u32 spinat; /* OTB -- spinat for mobile router */
int direction; /* in/out */
__u16 hit_magic; /* for quick checksum calculation */
sockaddr_list *src_addrs; /* source addresses */
sockaddr_list *dst_addrs; /* destination addresses */
/* inner addresses for BEET SAs (the above addresses
* are used as outer addresses) */
sockaddr_list *inner_src_addrs;
sockaddr_list *inner_dst_addrs;
__u32 mode; /* ESP mode : 0-default 1-transport 2-tunnel 3-beet */
__u16 dst_port; /* UDP dest. port for encaps. ESP */
struct timeval usetime_ka; /* last used timestamp, incl keep-alives */
struct sockaddr_storage lsi; /* LSI */
struct sockaddr_storage lsi6; /* IPv6 LSI (peer HIT) */
__u32 a_type; /* crypto parameters */
__u32 e_type;
__u32 a_keylen;
__u32 e_keylen;
__u8 *a_key; /* raw crypto keys */
__u8 *e_key;
__u64 lifetime; /* seconds until expiration */
__u64 bytes; /* bytes transmitted */
struct timeval usetime; /* last used timestamp */
__u32 sequence; /* sequence number counter */
__u32 replay_win; /* anti-replay window */
__u32 replay_map; /* anti-replay bitmap */
char iv[8];
des_key_schedule ks[3]; /* 3-DES keys */
AES_KEY *aes_key; /* AES key */
BF_KEY *bf_key; /* BLOWFISH key */
hip_mutex_t rw_lock;
} hip_sadb_entry;
/* HIP SADB desintation cache entry */
typedef struct _hip_sadb_dst_entry
{
struct _hip_sadb_dst_entry *next;
struct sockaddr_storage addr;
hip_sadb_entry *sadb_entry;
hip_mutex_t rw_lock;
} hip_sadb_dst_entry;
/* HIP LSI table entry */
#define LSI_PKT_BUFFER_SIZE 2000
#define LSI_ENTRY_LIFETIME 5
typedef struct _hip_lsi_entry
{
struct _hip_lsi_entry *next;
struct sockaddr_storage addr;
struct sockaddr_storage lsi4;
struct sockaddr_storage lsi6;
__u8 packet_buffer[LSI_PKT_BUFFER_SIZE];
int num_packets;
int next_packet;
int send_packets;
struct timeval creation_time;
} hip_lsi_entry;
/* protocol selector entry */
#define PROTO_SEL_SIZE 512
#define PROTO_SEL_ENTRY_LIFETIME 900
#define PROTO_SEL_DEFAULT_FAMILY AF_INET
#define hip_proto_sel_hash(a) (a % PROTO_SEL_SIZE)
typedef struct _hip_proto_sel_entry
{
struct _hip_proto_sel_entry *next;
__u32 selector; /* upper layer protocol-specific selector */
int family; /* guidance on which address family to use */
struct timeval last_used;
} hip_proto_sel_entry;
/*
* functions
*/
void hip_sadb_init();
void hip_sadb_deinit();
int hip_sadb_add(__u32 type, __u32 mode, struct sockaddr *inner_src,
struct sockaddr *inner_dst, struct sockaddr *src, struct sockaddr *dst, __u16 port,
__u32 spi, __u8 *e_key, __u32 e_type, __u32 e_keylen, __u8 *a_key,
__u32 a_type, __u32 a_keylen, __u32 lifetime, __u16 hitmagic, __u32 spinat);
int hip_sadb_delete(__u32 type, struct sockaddr *src, struct sockaddr *dst,
__u32 spi);
void hip_remove_expired_lsi_entries();
void hip_add_lsi(struct sockaddr *addr, struct sockaddr *lsi4,
struct sockaddr *lsi6);
int buffer_packet(struct sockaddr *lsi, __u8 *data, int len);
void unbuffer_packets(hip_lsi_entry *entry);
hip_lsi_entry *hip_lookup_lsi(struct sockaddr *lsi);
hip_sadb_entry *hip_sadb_lookup_spi(__u32 spi);
hip_sadb_entry *hip_sadb_lookup_addr(struct sockaddr *addr);
hip_sadb_entry *hip_sadb_get_next(hip_sadb_entry *placemark);
int hip_select_family_by_proto(__u32 lsi, __u8 proto, __u8 *header,
struct timeval *now);
int hip_add_proto_sel_entry(__u32 lsi, __u8 proto, __u8 *header, int family,
int dir, struct timeval *now);
void hip_remove_expired_sel_entries();
void print_sadb();

View File

@ -0,0 +1,109 @@
/*
* Host Identity Protocol
* Copyright (C) 2002-04 the Boeing Company
*
* 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 2 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.
*
* hip_service.h
*
* Authors: Jeff Ahrenholz <jeffrey.m.ahrenholz@boeing.com>
*
* Definition of HIP Windows service thread functions.
*
*/
#ifdef __WIN32__
#include <winsock2.h>
#include <ws2tcpip.h>
#include <time.h>
#else
#include <sys/socket.h> /* struct sockaddr */
#endif
/*
* Globally-accessible functions
*/
/* Windows _beghinthread() uses different type than pthread_create() */
#ifdef __WIN32__
void hip_esp_output(void *arg);
void hip_esp_input(void *arg);
void hip_pfkey(void *arg);
void tunreader(void *arg);
void hip_dns(void *arg);
void hipd_main(void *arg);
void hip_netlink(void *arg);
void hip_status(void *arg);
void udp_esp_keepalive(void *arg);
void udp_hip_keepalive(void *arg);
extern int socketpair(int, int, int, int sv[2]);
#define RETNULL ;
#else
void *hip_esp_output(void *arg);
void *hip_esp_input(void *arg);
void *hip_pfkey(void *arg);
void *tunreader(void *arg);
void *hip_dns(void *arg);
void *hipd_main(void *arg);
void *hip_netlink(void *arg);
void *hip_status(void *arg);
void *udp_esp_keepalive(void *arg);
void *udp_hip_keepalive(void *arg);
#define RETNULL NULL;
#endif
int pfkey_send_acquire(struct sockaddr *target);
extern void hip_sleep(int seconds);
/*
* Global definitions
*/
#ifdef __MACOSX__
#include <mac/mac_types.h>
#else
#ifndef __WIN32__
#include <asm/types.h>
#endif
#endif
#ifndef CONFIG_HIP
#define CONFIG_HIP
#endif
#define DNS_PORT 53
#define HIP_DNS_SUFFIX ".hip"
#define HIP_UDP_PORT 50500
extern __u64 g_tap_mac;
extern int g_state;
/*#ifndef HIP_ESP_UDP_PORT*/
#define HIP_ESP_UDP_PORT 54500
/*#endif*/
#define KEEPALIVE_TIMEOUT 20
/* from linux/include/linux/kernel.h */
#define NIPQUAD(addr) \
((unsigned char *)&addr)[0], \
((unsigned char *)&addr)[1], \
((unsigned char *)&addr)[2], \
((unsigned char *)&addr)[3]
#define NIP6(addr) \
ntohs((addr).s6_addr16[0]), \
ntohs((addr).s6_addr16[1]), \
ntohs((addr).s6_addr16[2]), \
ntohs((addr).s6_addr16[3]), \
ntohs((addr).s6_addr16[4]), \
ntohs((addr).s6_addr16[5]), \
ntohs((addr).s6_addr16[6]), \
ntohs((addr).s6_addr16[7])
#define TRUE 1
#define FALSE 0

View File

@ -0,0 +1,127 @@
/*
* Host Identity Protocol
* Copyright (C) 2005 the Boeing Company
*
* 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 2 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.
*
* hip_status.h
*
* Authors: Jeff Ahrenholz <jeffrey.m.ahrenholz@boeing.com>
*
* Status thread definitions.
* This file is shared by hipd, the Windows service, and status reporting
* helper apps.
*
*/
#ifndef __HIP_STATUS_H_
#define __HIP_STATUS_H_
/*
* Globals
*/
#define WIN_STATUS_PORT 4052
#define STATUS_PORT 4051
/*
* Types and macros
*/
struct status_tlv
{
unsigned short tlv_type;
unsigned short tlv_len;
};
#define ADD_ITEM(a, b, c) memcpy(&a[c], &b, sizeof(b)); c += sizeof(b);
/*
* Status request types serviced by hipd
*/
enum requests {
HIP_STATUS_REQ_MIN,
HIP_STATUS_REQ_PEERS,
HIP_STATUS_REQ_MYIDS,
HIP_STATUS_REQ_MYADDRS,
HIP_STATUS_REQ_ASSOC,
HIP_STATUS_REQ_OPTS,
HIP_STATUS_REQ_CONF,
HIP_STATUS_REQ_MAX
};
enum settings {
HIP_STATUS_CONFIG_MIN = HIP_STATUS_REQ_MAX,
HIP_STATUS_CONFIG_OPTS,
HIP_STATUS_CONFIG_MAX
};
/*
* Status request types handled by the Windows service
*/
enum win_requests {
STAT_MIN,
STAT_THREADS,
STAT_SADB,
STAT_DST,
STAT_LSI,
STAT_PEERS,
STAT_IDS,
STAT_ALL_SPI,
STAT_MAX
};
enum responses {
HIP_STATUS_REPLY_MIN,
HIP_STATUS_REPLY_ERROR,
HIP_STATUS_REPLY_STRING,
HIP_STATUS_REPLY_SADB,
HIP_STATUS_REPLY_ADDR,
HIP_STATUS_REPLY_DST_ENTRY,
HIP_STATUS_REPLY_LSI_ENTRY,
HIP_STATUS_REPLY_HI,
HIP_STATUS_REPLY_ASSOC,
HIP_STATUS_REPLY_OPTS,
HIP_STATUS_REPLY_ALL_SPI,
HIP_STATUS_REPLY_DONE,
HIP_STATUS_REPLY_MAX
};
/* Problems with multiple definitions of the arrays below */
#ifndef __UMH__
/*
* Useful text definitions
*/
const char enc_alg_texts[7][28] = {
"",
"AES CBC with HMAC SHA1",
"3DES CBC with HMAC SHA1",
"3DES CBC with HMAC MD5",
"BLOWFISH CBC with HMAC SHA1",
"NULL with HMAC SHA1",
"NULL with HMAC MD5",
};
const char state_texts[9][16] = {
"Unassociated",
"I1 Sent",
"I2 Sent",
"R2 Sent",
"Established",
"Rekeying",
"Closing",
"Closed",
"E Failed",
};
#endif
#endif /* __HIP_STATUS_H_ */

406
src/include/hip/hip_stun.h Normal file
View File

@ -0,0 +1,406 @@
/*
* Host Identity Protocol
*
* STUN client based on the code provided by Vovida Networks, Inc.
* (see end of file)
* Translated from C++ code to C code by Vivien Schmitt
*
* hip_stun.h
*
* Author : Vivien Schmitt, <schmitt@netlab.nec.de>
*
* STUN client used for NAT detection
*
*/
#ifndef STUN_H
#define STUN_H
#include <time.h>
#include "hip_stun_udp.h"
#define TRUE 1
#define FALSE 0
/* if you change this version, change in makefile too */
#define STUN_VERSION "0.96"
#define STUN_MAX_STRING 256
#define STUN_MAX_UNKNOWN_ATTRIBUTES 8
#define STUN_MAX_MESSAGE_SIZE 2048
#define STUN_PORT 3478
/* define some basic types*/
typedef unsigned char UInt8;
typedef unsigned short UInt16;
typedef unsigned int UInt32;
#ifdef __WIN32__
typedef __u64 UInt64;
#else
typedef unsigned long long UInt64;
#endif /* __WIN32__ */
typedef struct { unsigned char octet[16]; } UInt128;
/*/ define a structure to hold a stun address */
extern UInt8 IPv4Family;
extern UInt8 IPv6Family;
/* define flags */
extern UInt32 ChangeIpFlag;
extern UInt32 ChangePortFlag;
/* define stun attribute*/
extern UInt16 MappedAddress;
extern UInt16 ResponseAddress;
extern UInt16 ChangeRequest;
extern UInt16 SourceAddress;
extern UInt16 ChangedAddress;
extern UInt16 Username;
extern UInt16 Password;
extern UInt16 MessageIntegrity;
extern UInt16 ErrorCode;
extern UInt16 UnknownAttribute;
extern UInt16 ReflectedFrom;
extern UInt16 XorMappedAddress;
extern UInt16 XorOnly;
extern UInt16 ServerName;
extern UInt16 SecondaryAddress; /* Non standard extention*/
/* define types for a stun message */
extern UInt16 BindRequestMsg;
extern UInt16 BindResponseMsg;
extern UInt16 BindErrorResponseMsg;
extern UInt16 SharedSecretRequestMsg;
extern UInt16 SharedSecretResponseMsg;
extern UInt16 SharedSecretErrorResponseMsg;
typedef struct
{
UInt16 msgType;
UInt16 msgLength;
UInt128 id;
} StunMsgHdr;
typedef struct
{
UInt16 type;
UInt16 length;
} StunAtrHdr;
typedef struct
{
UInt16 port;
UInt32 addr;
} StunAddress4;
typedef struct
{
UInt8 pad;
UInt8 family;
StunAddress4 ipv4;
} StunAtrAddress4;
typedef struct
{
UInt32 value;
} StunAtrChangeRequest;
typedef struct
{
UInt16 pad; /* all 0*/
UInt8 errorClass;
UInt8 number;
char reason[STUN_MAX_STRING];
UInt16 sizeReason;
} StunAtrError;
typedef struct
{
UInt16 attrType[STUN_MAX_UNKNOWN_ATTRIBUTES];
UInt16 numAttributes;
} StunAtrUnknown;
typedef struct
{
char value[STUN_MAX_STRING];
UInt16 sizeValue;
} StunAtrString;
typedef struct
{
char hash[20];
} StunAtrIntegrity;
typedef enum
{
HmacUnkown=0,
HmacOK,
HmacBadUserName,
HmacUnkownUserName,
HmacFailed,
} StunHmacStatus;
typedef struct
{
StunMsgHdr msgHdr;
int hasMappedAddress;
StunAtrAddress4 mappedAddress;
int hasResponseAddress;
StunAtrAddress4 responseAddress;
int hasChangeRequest;
StunAtrChangeRequest changeRequest;
int hasSourceAddress;
StunAtrAddress4 sourceAddress;
int hasChangedAddress;
StunAtrAddress4 changedAddress;
int hasUsername;
StunAtrString username;
int hasPassword;
StunAtrString password;
int hasMessageIntegrity;
StunAtrIntegrity messageIntegrity;
int hasErrorCode;
StunAtrError errorCode;
int hasUnknownAttributes;
StunAtrUnknown unknownAttributes;
int hasReflectedFrom;
StunAtrAddress4 reflectedFrom;
int hasXorMappedAddress;
StunAtrAddress4 xorMappedAddress;
int xorOnly;
int hasServerName;
StunAtrString serverName;
int hasSecondaryAddress;
StunAtrAddress4 secondaryAddress;
} StunMessage;
/* Define enum with different types of NAT */
typedef enum
{
StunTypeUnknown=0,
StunTypeFailure,
StunTypeOpen,
StunTypeBlocked,
StunTypeIndependentFilter,
StunTypeDependentFilter,
StunTypePortDependedFilter,
StunTypeDependentMapping,
StunTypeFirewall,
} NatType;
#define MAX_MEDIA_RELAYS 500
#define MAX_RTP_MSG_SIZE 1500
#define MEDIA_RELAY_TIMEOUT 3*60
typedef struct
{
int relayPort; /* media relay port*/
int fd; /* media relay file descriptor*/
StunAddress4 destination; /* NAT IP:port*/
time_t expireTime; /* if no activity after time, close the socket */
} StunMediaRelay;
typedef struct
{
StunAddress4 myAddr;
StunAddress4 altAddr;
int myFd;
int altPortFd;
int altIpFd;
int altIpPortFd;
int relay; /* true if media relaying is to be done */
StunMediaRelay relays[MAX_MEDIA_RELAYS];
} StunServerInfo;
int
stunParseMessage( char* buf,
unsigned int bufLen,
StunMessage *message,
int verbose );
void
stunBuildReqSimple( StunMessage* msg,
const StunAtrString *username,
int changePort, int changeIp, unsigned int id);
unsigned int
stunEncodeMessage( const StunMessage *message,
char* buf,
unsigned int bufLen,
const StunAtrString *password,
int verbose);
void
stunCreateUserName(const StunAddress4 *addr, StunAtrString* username);
void
stunGetUserNameAndPassword( const StunAddress4 *dest,
StunAtrString* username,
StunAtrString* password);
void
stunCreatePassword(const StunAtrString *username, StunAtrString* password);
void printIPv4Addr (const StunAddress4 *ad);
void printUInt128 (UInt128 r);
int
stunRand();
UInt64
stunGetSystemTimeSecs();
/*/ find the IP address of a the specified stun server - return false is fails parse */
int
stunParseServerName( char* serverName, StunAddress4 *stunServerAddr);
int
stunParseHostName( char* peerName,
UInt32 *ip,
UInt16 *portVal,
UInt16 defaultPort );
/*/ return true if all is OK
/// Create a media relay and do the STERN thing if startMediaPort is non-zero*/
int
stunInitServer(StunServerInfo *info,
const StunAddress4 *myAddr,
const StunAddress4 *altAddr,
int startMediaPort,
int verbose);
void
stunStopServer(StunServerInfo *info);
/*/ return true if all is OK */
int
stunServerProcess(StunServerInfo *info, int verbose);
/*/ returns number of address found - take array or addres */
int
stunFindLocalInterfaces(UInt32* addresses, int maxSize );
void
stunTest( StunAddress4 *dest, int testNum, int verbose, StunAddress4* srcAddr );
NatType
stunNatType( StunAddress4 *dest, int verbose,
int* preservePort, /* if set, is return for if NAT preservers ports or not */
int* hairpin , /* if set, is the return for if NAT will hairpin packets */
int port, /* port to use for the test, 0 to choose random port */
StunAddress4* sAddr /* NIC to use */
);
/*/ prints a StunAddress */
/*std::ostream &
operator<<( std::ostream& strm, const StunAddress4& addr);
std::ostream&
operator<< ( std::ostream& strm, const UInt128& );
*/
int
stunServerProcessMsg( char* buf,
unsigned int bufLen,
StunAddress4 *from,
StunAddress4 *secondary,
StunAddress4 *myAddr,
StunAddress4 *altAddr,
StunMessage* resp,
StunAddress4* destination,
StunAtrString* hmacPassword,
int* changePort,
int* changeIp,
int verbose);
int
stunOpenSocket( StunAddress4 *dest,
StunAddress4* mappedAddr,
int port,
StunAddress4* srcAddr,
int verbose );
int
stunOpenSocketPair( StunAddress4 *dest, StunAddress4* mappedAddr,
int* fd1, int* fd2,
int srcPort, StunAddress4* srcAddr,
int verbose);
int
stunRandomPort();
#endif
/* ====================================================================
* The Vovida Software License, Version 1.0
*
* Copyright (c) 2000 Vovida Networks, Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The names "VOCAL", "Vovida Open Communication Application Library",
* and "Vovida Open Communication Application Library (VOCAL)" must
* not be used to endorse or promote products derived from this
* software without prior written permission. For written
* permission, please contact vocal@vovida.org.
*
* 4. Products derived from this software may not be called "VOCAL", nor
* may "VOCAL" appear in their name, without prior written
* permission of Vovida Networks, Inc.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
* NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA
* NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
* IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*
* ====================================================================
*
* This software consists of voluntary contributions made by Vovida
* Networks, Inc. and many individuals on behalf of Vovida Networks,
* Inc. For more information on Vovida Networks, Inc., please see
* <http://www.vovida.org/>.
*
*/

View File

@ -0,0 +1,114 @@
/*
* Host Identity Protocol
*
* STUN client based on the code provided by Vovida Networks, Inc.
* (see end of file)
* Translated from C++ code to C code by Vivien Schmitt
*
* hip_stun_udp.h
*
* Author : Vivien Schmitt, <schmitt@netlab.nec.de>
*
* STUN client used for NAT detection
*
*/
#ifndef stun_udp_h
#define stun_udp_h
#define TRUE 1
#define FALSE 0
#include <errno.h>
#ifndef __WIN32__
static const int INVALID_SOCKET = -1;
static const int SOCKET_ERROR = -1;
int closesocket( int fd );
int getErrno();
#define WSANOTINITIALISED EPROTONOSUPPORT
#endif /* __WIN32__ */
/*
/// Open a UDP socket to receive on the given port - if port is 0, pick a a
/// port, if interfaceIp!=0 then use ONLY the interface specified instead of
/// all of them */
int
openPort( unsigned short port, unsigned int interfaceIp,
int verbose);
/*/ recive a UDP message */
int
getMessage( int fd, char* buf, int* len,
unsigned int* srcIp, unsigned short* srcPort,
int verbose);
/*/ send a UDP message */
int
sendMessage( int fd, char* msg, int len,
unsigned int dstIp, unsigned short dstPort,
int verbose);
/* ====================================================================
* The Vovida Software License, Version 1.0
*
* Copyright (c) 2000 Vovida Networks, Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The names "VOCAL", "Vovida Open Communication Application Library",
* and "Vovida Open Communication Application Library (VOCAL)" must
* not be used to endorse or promote products derived from this
* software without prior written permission. For written
* permission, please contact vocal@vovida.org.
*
* 4. Products derived from this software may not be called "VOCAL", nor
* may "VOCAL" appear in their name, without prior written
* permission of Vovida Networks, Inc.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
* NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA
* NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
* IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*
* ====================================================================
*
* This software consists of voluntary contributions made by Vovida
* Networks, Inc. and many individuals on behalf of Vovida Networks,
* Inc. For more information on Vovida Networks, Inc., please see
* <http://www.vovida.org/>.
*
*/
#endif

931
src/include/hip/hip_types.h Normal file
View File

@ -0,0 +1,931 @@
/*
* Host Identity Protocol
* Copyright (C) 2002-05 the Boeing Company
*
* 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 2 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.
*
* Definitions for the HIP protocol.
*
* Version: @(#)hip.h 1.5 08/12/04
*
* Authors: Jeff Ahrenholz, <jeffrey.m.ahrenholz@boeing.com>
* Tom Henderson, <thomas.r.henderson@boeing.com>
*
*
*/
#ifndef _HIP_TYPES_H_
#define _HIP_TYPES_H_
/* XXX clean up type portability */
#if defined (__MACOSX__)
#include <mac/mac_types.h>
#elif defined (__WIN32__)
#include <win32/types.h>
#else /* Linux */
#include <asm/types.h>
#endif
#ifdef __MACOSX__
#include <sys/types.h>
#include <sys/time.h>
#endif
#ifdef __WIN32__
#include <winsock2.h>
#else
#include <sys/socket.h> /* sockaddr */
#include <netinet/in.h>
#endif
#include <sys/types.h>
#include <openssl/bn.h>
#include <openssl/hmac.h>
#include <openssl/rsa.h>
#include <time.h>
#include <hip/hip_proto.h>
#ifdef SMA_CRAWLER
#define NIPQUAD(addr) \
((unsigned char *)&addr)[0], \
((unsigned char *)&addr)[1], \
((unsigned char *)&addr)[2], \
((unsigned char *)&addr)[3]
#endif
/*
* Implementation configuration options
*/
#define HIP_CONF_FILENAME "hip.conf"
#define HIP_MYID_FILENAME "my_host_identities.xml"
#define HIP_KNOWNID_FILENAME "known_host_identities.xml"
#define HIP_REG_FILENAME "registered_host_identities.xml"
#define HIP_PUB_PREFIX ""
#define HIP_PUB_SUFFIX "_host_identities.pub.xml"
#define HIP_LOCK_FILENAME "hip.pid"
#define HIP_LOG_FILENAME "hipd.log"
/*
* Implementation limits
*/
#ifdef SMA_CRAWLER
#define MAX_HITS 255
#define MAX_CONNECTIONS 255
#else
#define MAX_HITS 32
#define MAX_CONNECTIONS 32 /* Should be == MAX_HITS */
#endif
#define MAX_LEGACY_HOSTS 255 /*how many legacy hosts can attached to an endbox */
#define MAX_OPAQUE_SIZE 255 /* how many bytes we may echo in response */
#define MAX_HI_NAMESIZE 255 /* number of bytes for HI Domain Identifier */
#define MAX_HI_BITS 2048 /* number of bits of largest HI accepted - this
* may limit the time spent w/ DSA verification */
#define MAX_LOCATORS 8 /* number of LOCATORs accepted in an UPDATE message */
#define MAX_REGISTRATIONS 1024 /* used in rvs mode */
#define MAX_REGISTRATION_TYPES 255 /* number of registration services */
#define MAX_MR_CLIENTS MAX_CONNECTIONS /* Number of mobile router clients */
/*
* IPsec-related constants
*/
#define DSA_PRIV 20 /* Size in bytes of DSA private key and Q value */
#define HIP_KEY_SIZE 24 /* Must be large enough to hold largest possible key */
#define HIP_DSA_SIG_SIZE 41 /* T(1) + R(20) + S(20) from RFC 2536 */
#define MAX_SIG_SIZE 512 /* RFC 3110 4096-bits max RSA length */
#define NUMKEYS 8 /* HIP, HMAC, HIP, HMAC, ESP, AUTH, ESP, AUTH */
#define KEYMAT_SIZE (4 * NUMKEYS * HIP_KEY_SIZE) /* 768 bytes, enough space for
32 ESP keys */
#define MAX_CERT_LEN 128 /* max lengh of a certificate URL */
/* 3DES keys = 192 bits, 24 bytes; SHA-1 keys = 160 bits, 20 bytes.
* We need 4 3DES and 2 SHA for our 6 keys, 136 bytes, so 144 is enough.
*/
/*
* Protocol constants
*/
#define HIP_RES_SHIM6_BITS 0x01
#define H_PROTO_UDP 17
#define HIP_ESP_UDP_PORT 54500
/* PFKEY message sizes*/
#define SADB_RESPONSE_BUFFER 20
#define SADB_MSG_SIZE_ADD 304
#define SADB_MSG_SIZE_DELETE 150
/*
* Miscellaneous constants and enums
*/
#define TRUE 1
#define FALSE 0
/*
#define UNKNOWN -1
*/
#define SPI_RESERVED 255
#define HIP_ALIGN 4
#define R1_CACHE_SIZE 8
#define ACCEPTABLE_R1_COUNT_RANGE 2
#ifndef HIP_UPDATE_BIND_CHECKS
#define HIP_UPDATE_BIND_CHECKS 5
#endif
/* Unoffical Registration states */
typedef enum {
REG_OFFERED,
REG_REQUESTED,
REG_SEND_RESP,
REG_GRANTED,
REG_SEND_FAILED,
REG_FAILED,
REG_SEND_CANCELLED,
REG_CANCELLED
} REG_STATES;
/* Official Failure Codes */
typedef enum {
REG_FAIL_REQ_ADD_CRED = 0,
REG_FAIL_TYPE_UNAVAIL
} REQ_FAILURE_CODES;
/*
* Macros
*/
#define DBG(x) x /* Debugging */
#define TDIFF(a, b) ((a).tv_sec - (b).tv_sec) /* Time diff in seconds */
/* get pointer to IP from a sockaddr
* useful for inet_ntop calls */
#define SA2IP(x) (((struct sockaddr*)x)->sa_family==AF_INET) ? \
(__u8*)&((struct sockaddr_in*)x)->sin_addr : \
(__u8*)&((struct sockaddr_in6*)x)->sin6_addr
/* get socket address length in bytes */
#define SALEN(x) (((struct sockaddr*)x)->sa_family==AF_INET) ? \
sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6)
/* get IP address length in bytes */
#define SAIPLEN(x) (((struct sockaddr*)x)->sa_family==AF_INET) ? 4 : 16
/* cast to sockaddr */
#define SA(x) ((struct sockaddr*)x)
/* boolean to text yes/no */
#define yesno(x) x ? "yes" : "no"
/* Host Identity Tag is 128 bits long */
#define HIT_SIZE 16
/* The below prefix applies to the uppermost 28 bits only (RFC 4843) */
#define HIT_PREFIX_SHA1_32BITS 0x20010010
/* convert lower 24-bits of HIT to LSI */
#define HIT2LSI(a) ( 0x01000000L | \
((a[HIT_SIZE-3]<<16)+(a[HIT_SIZE-2]<<8)+(a[HIT_SIZE-1])))
/* compute the exponent of registration lifetime */
#define YLIFE(x) ((float)x-(float)64)/(float)8
/*
* typedefs
*/
typedef __u8 hip_hit [HIT_SIZE]; /* 16-byte (128 bit) Host Identity Tag */
#ifdef __WIN32__
typedef HANDLE hip_mutex_t;
#else
typedef pthread_mutex_t hip_mutex_t;
#endif
#define HIP_UDP_PORT 50500
#define HIP_KEEPALIVE_TIMEOUT 20
/*
* UDP header, used for UDP encapsulation
*/
typedef struct _udphdr {
__u16 src_port;
__u16 dst_port;
__u16 len;
__u16 checksum;
} udphdr;
/*
* HIP header
* This HIP protocol header defines the structure of HIP packets.
*/
typedef struct _hiphdr {
__u8 nxt_hdr; /* payload protocol */
__u8 hdr_len; /* header length */
__u8 packet_type; /* packet type */
#if defined(__MACOSX__) && defined(__BIG_ENDIAN__)
__u8 version:4,res:4; /* Endian - not OSX specific */
#else
__u8 res:4,version:4; /* version, reserved */
#endif
__u16 checksum; /* checksum */
__u16 control; /* control */
hip_hit hit_sndr; /* Sender's Host Identity Tag */
hip_hit hit_rcvr; /* Receiver's Host Identity Tag */
/* HIP TLV parameters follow ... */
} hiphdr;
/*
* HIP Cookie
*/
typedef struct _hipcookie {
__u8 k;
__u8 lifetime;
__u16 opaque;
__u64 i __attribute__ ((packed));
} hipcookie;
struct key_entry {
int type;
int length;
__u8 key[HIP_KEY_SIZE];
};
struct rekey_info {
__u32 update_id; /* to be ACKed */
__u32 new_spi; /* SPI that will be adopted */
__u16 keymat_index; /* keymat index */
__u8 acked;/* set to TRUE when update_id has been ACKed */
__u8 dh_group_id; /* new DH group given by peer */
DH *dh; /* new DH given by the peer */
struct timeval rk_time; /* creation time, so struct can be freed */
};
/*
* HIP Packet Entry
*/
struct hip_packet_entry {
__u8 *packet;
int len;
struct timeval xmit_time;
__u32 retransmits;
struct sockaddr_storage dst; /* for address checks */
};
/*
* Registration types
*/
struct reg_info {
__u8 type;
int state;
struct timeval state_time;
__u8 failure_code;
__u8 requested_lifetime;
__u8 granted_lifetime;
struct reg_info *next;
};
struct reg_entry {
int number;
struct reg_info *regs;
__u8 min_lifetime;
__u8 max_lifetime;
};
/*
* HIP association entry
*
*/
typedef struct _hip_assoc {
/* Identities */
struct _hi_node *hi;
struct _hi_node *peer_hi;
/* Misc. state variables */
int state;
struct timeval state_time;
struct timeval use_time;
__u64 used_bytes_in;
__u64 used_bytes_out;
__u32 spi_in;
__u32 spi_out;
__u32 spi_nat;
hipcookie cookie_r;
__u64 cookie_j;
struct hip_packet_entry rexmt_cache;
struct opaque_entry *opaque;
struct reg_entry *reg_offered;
struct reg_entry *reg_requested;
struct rekey_info *rekey; /* new parameters to use after REKEY */
struct rekey_info *peer_rekey; /* peer's REKEY data from UPDATE */
/* Other crypto */
__u16 hip_transform;
__u16 esp_transform;
__u16 available_transforms; /* bit mask used to flag available xfrms */
__u8 dh_group_id;
DH *dh;
DH *peer_dh; /* needed for rekeying */
__u8 *dh_secret; /* without packing, these cause memset segfaults! */
__u16 keymat_index;
__u16 mr_keymat_index;
__u8 keymat[KEYMAT_SIZE];
struct key_entry keys[NUMKEYS];
struct key_entry mr_key;
__u8 preserve_outbound_policy;
int use_udp; /* 0: no UDP / 1: HIP over UDP */
int next_use_udp; /* used during UPDATE, when rekeying has not been completed */
__u16 peer_dst_port; /* UDP port number used by the peer for HIP packets */
struct timeval use_time_ka; /* last use timestamp, including keepalives */
__u16 peer_esp_dst_port; /* UDP port number used by the peer for ESP packets */
#ifdef __MACOSX__
__u16 ipfw_rule;
#endif
} hip_assoc;
#define HIPA_SRC(h) ((struct sockaddr*)&h->hi->addrs.addr)
#define HIPA_DST(h) ((struct sockaddr*)&h->peer_hi->addrs.addr)
/*
* HIP registration entry
*
*/
typedef struct _hip_reg {
hip_hit peer_hit;
hip_mutex_t peer_addr_mutex;
struct sockaddr_storage peer_addr;
double lifetime;
int update;
hip_assoc *hip_a;
} hip_reg;
/*
* Struct to use with the search_reg_table
*/
typedef struct _returned {
int position;
int update;
} returned;
/*
* Structs used in the relaying I1 process
*/
typedef struct _from {
int add_from;
hip_hit hit_from;
struct sockaddr_storage ip_rvs;
struct sockaddr_storage ip_from;
} from;
typedef struct _via {
int add_via_rvs;
struct sockaddr_storage ip_from;
} via;
/*
* list of struct sockaddrs
*/
typedef struct _sockaddr_list
{
struct _sockaddr_list *next;
struct sockaddr_storage addr; /* 128 bytes, enough to store any size */
int if_index; /* link index */
int lifetime; /* address lifetime in seconds*/
int status; /* status from enum ADDRESS_STATES */
int preferred; /* set to TRUE if it's a new pending preferred addr */
__u32 nonce; /* random value for address verification */
struct timeval creation_time;
} sockaddr_list;
/*
* R1 Cache
*/
typedef struct _r1_cache_entry
{
/* the precomputed R1 packet */
__u8 *packet;
int len;
/* stored cookie solutions */
hipcookie *current_puzzle; /* the cookie that is in packet */
hipcookie *previous_puzzle; /* old cookie */
/* the DH context used in the R1 */
struct _dh_cache_entry *dh_entry;
/* time of entry creation */
struct timeval creation_time;
} r1_cache_entry;
/* For reference: struct DSA definition from openssl/dsa.h */
/*
* struct dsa_st {
*
* * This first variable is used to pick up errors where
* * a DSA is passed instead of of a EVP_PKEY *
int pad;
int version;
int write_params;
BIGNUM *p;
BIGNUM *q; * == 20 *
BIGNUM *g;
BIGNUM *pub_key; * y public key *
BIGNUM *priv_key; * x private key *
... (plus some other fields not used in HIP)
*/
typedef struct _hi_node {
struct _hi_node *next;
hip_hit hit;
struct sockaddr_storage lsi;
struct sockaddr_storage rvs;
/*
* IP address is needed to select a HIT corresponding to
* an IP address. This value needs update upon readdress.
* Only the first entry of addrs is used for hip_assoc,
* while the list addrs->next is populated when building the
* HI tables.
*/
hip_mutex_t addrs_mutex; /* provide DHT thread synchronization */
struct _sockaddr_list addrs;
/* Key data */
int size; /* Size in bytes of the Host Identity */
DSA *dsa; /* HI in DSA format */
RSA *rsa; /* HI in RSA format */
struct _r1_cache_entry r1_cache[R1_CACHE_SIZE]; /* the R1 cache */
__u64 r1_gen_count; /* R1 generation counter */
__u32 update_id; /* this host's Update ID */
/* Options */
char algorithm_id;
char anonymous;
char allow_incoming;
char skip_addrcheck;
char name[MAX_HI_NAMESIZE];
int name_len; /* use this instead of strlen() */
} hi_node;
struct peer_node
{
hip_hit hit;
int size; /* Size in bytes of the Host Identity */
__u64 r1_gen_count;
char algorithm_id;
char anonymous;
char allow_incoming;
char skip_addrcheck;
char name[MAX_HI_NAMESIZE];
struct sockaddr_storage rvs;
};
/* DH Cache
*/
typedef struct _dh_cache_entry
{
struct _dh_cache_entry *next; /* the cache is a linked-list */
__u8 group_id; /* can have various group_ids */
DH *dh; /* the Diffie-Hellman context */
__u8 is_current; /* if this is the latest DH context
for this group_id, then TRUE */
int ref_count; /* number of hip_assoc that point to this entry */
struct timeval creation_time; /* determines age */
} dh_cache_entry;
/* Opaque Data
*/
struct opaque_entry
{
__u16 opaque_len;
__u8 opaque_data[MAX_OPAQUE_SIZE];
__u8 opaque_nosig;
};
typedef struct _pseudo_header6
{
unsigned char src_addr[16];
unsigned char dst_addr[16];
__u32 packet_length;
char zero[3];
__u8 next_hdr;
} pseudo_header6;
typedef struct _pseudo_header
{
unsigned char src_addr[4];
unsigned char dst_addr[4];
__u8 zero;
__u8 protocol;
__u16 packet_length;
} pseudo_header;
/*
* TLV parameters
*/
typedef struct _tlv_head
{
__u16 type;
__u16 length;
} tlv_head;
typedef struct _tlv_esp_info
{
__u16 type;
__u16 length;
__u16 reserved;
__u16 keymat_index;
__u32 old_spi;
__u32 new_spi;
} tlv_esp_info;
typedef struct _tlv_r1_counter
{
__u16 type;
__u16 length;
__u32 reserved;
__u64 r1_gen_counter;
} tlv_r1_counter;
typedef struct _tlv_puzzle
{
__u16 type;
__u16 length;
hipcookie cookie;
} tlv_puzzle;
typedef struct _tlv_solution
{
__u16 type;
__u16 length;
hipcookie cookie;
__u64 j;
} tlv_solution;
typedef struct _tlv_diffie_hellman
{
__u16 type;
__u16 length;
__u8 group_id;
__u16 pub_len;
__u8 pub[1]; /* variable length */
} __attribute__ ((packed)) tlv_diffie_hellman;
/* used for second DH public value */
typedef struct _tlv_diffie_hellman_pub_value
{
__u8 group_id;
__u16 pub_len;
__u8 pub[1]; /* variable length */
} __attribute__ ((packed)) tlv_diffie_hellman_pub_value;
typedef struct _tlv_hip_transform
{
__u16 type;
__u16 length;
__u16 transform_id;
} tlv_hip_transform;
typedef struct _tlv_esp_transform
{
__u16 type;
__u16 length;
__u16 reserved; /* LSB is E-bit */
__u16 suite_id;
} tlv_esp_transform;
typedef struct _tlv_encrypted
{
__u16 type;
__u16 length;
__u8 reserved[4];
__u8 iv[8]; /* 64-bits for 3-DES and Blowfish */
/* adjust for 128-bits if using AES */
__u8 enc_data[1]; /* variable length */
} tlv_encrypted;
typedef struct _tlv_host_id
{
__u16 type;
__u16 length;
__u16 hi_length;
__u16 di_type_length;
__u8 hi_hdr[4];
/* for DSA: for RSA:
* __u8 hi_t; __u8 e_len
* __u8 hi_q[DSA_PRIV]; __u8 e[1] or __u8 e[3];
* P, G, Y are here, variable __u8 n[]; variable
* length based on t (64 + 3*t)
*
* also DI is variable
*
*/
} tlv_host_id;
typedef struct _tlv_cert
{
__u16 type;
__u16 length;
__u8 cert_group;
__u8 cert_count;
__u8 cert_id;
__u8 cert_type;
__u8 certificate[1]; /* variable length */
} tlv_cert;
typedef struct _tlv_reg_info
{
__u16 type;
__u16 length;
__u8 min_lifetime; /* defined as in draft-koponen-hip-registration-01 (exponential lifetime) */
__u8 max_lifetime; /* defined as in draft-koponen-hip-registration-01 (exponential lifetime) */
__u8 reg_type; /* reg_type_rvs = 1 by default. no other registration types defined yet */
} tlv_reg_info;
typedef struct _tlv_reg_request
{
__u16 type;
__u16 length;
__u8 lifetime;
__u8 reg_type;
} tlv_reg_request;
typedef struct _tlv_reg_response
{
__u16 type;
__u16 length;
__u8 lifetime;
__u8 reg_type;
} tlv_reg_response;
typedef struct _tlv_reg_failed
{
__u16 type;
__u16 length;
__u8 fail_type; /* if 1, error in registration type */
__u8 reg_type;
} tlv_reg_failed;
#ifndef __WIN32__
typedef struct _tlv_reg_required
{
/* TBD */ /* parameter to use in a NOTIFY packet */
} tlv_reg_required;
#endif /* __WIN32__ */
typedef struct _tlv_echo /* response and request the same */
{
__u16 type;
__u16 length;
__u8 opaque_data[1]; /* variable length */
} tlv_echo;
typedef struct _tlv_hmac
{
__u16 type;
__u16 length;
__u8 hmac[20];
} tlv_hmac;
typedef struct _tlv_hip_sig
{
__u16 type;
__u16 length;
__u8 algorithm;
__u8 signature[0]; /* variable length */
} tlv_hip_sig;
typedef struct _tlv_seq
{
__u16 type;
__u16 length;
__u32 update_id;
} tlv_seq;
typedef struct _tlv_ack
{
__u16 type;
__u16 length;
__u32 peer_update_id;
} tlv_ack;
typedef struct _tlv_notify
{
__u16 type;
__u16 length;
__u16 reserved;
__u16 notify_type;
__u8 notify_data[0]; /* variable length */
} tlv_notify;
typedef struct _locator
{
__u8 traffic_type;
__u8 locator_type;
__u8 locator_length;
__u8 reserved;
__u32 locator_lifetime;
__u8 locator[20]; /* 32-bit SPI + 128-bit IPv6/IPv4-in-IPv6 address */
} locator;
#define LOCATOR_PREFERRED 0x01
#define LOCATOR_TRAFFIC_TYPE_BOTH 0x00
#define LOCATOR_TRAFFIC_TYPE_SIGNALING 0x01
#define LOCATOR_TRAFFIC_TYPE_DATA 0x02
#define LOCATOR_TYPE_IPV6 0x00
#define LOCATOR_TYPE_SPI_IPV6 0x01
typedef struct _tlv_locator
{
__u16 type;
__u16 length;
locator locator1[1]; /* one or more */
} tlv_locator;
typedef struct _tlv_from
{
__u16 type;
__u16 length;
unsigned char addr[16];
} tlv_from;
typedef struct _tlv_rvs_hmac
{
__u16 type;
__u16 length;
__u8 hmac[20];
} tlv_rvs_hmac;
typedef struct _tlv_via_rvs
{
__u16 type;
__u16 length;
__u8 address[16];
} tlv_via_rvs;
typedef struct _tlv_proxy_ticket
{
__u16 type;
__u16 length;
hip_hit mn_hit;
hip_hit peer_hit;
__u8 hmac_key[20];
__u16 hmac_key_index;
__u16 transform_type;
__u16 action;
__u16 lifetime;
__u8 hmac[20];
} tlv_proxy_ticket;
typedef struct _tlv_auth_ticket
{
__u16 type;
__u16 length;
__u16 hmac_key_index;
__u16 transform_type;
__u16 action;
__u16 lifetime;
__u8 hmac[20];
} tlv_auth_ticket;
/*
* Struct to use in the set_lifetime_thread
*/
typedef struct _thread_arg{
hiphdr hip_header;
tlv_reg_response resp;
} thread_arg;
/*
* Logging
*/
typedef enum {
D_DEFAULT,
D_VERBOSE,
D_QUIET,
} DEBUG_MODES;
typedef enum {
NORM,
NORMT,
WARN,
ERR,
QOUT,
} LOG_LEVELS;
/*
* Global options
*/
struct hip_opt {
int daemon;
int debug;
int debug_R1;
int no_retransmit;
int permissive;
int opportunistic;
int allow_any;
int enable_udp;
struct sockaddr *trigger;
int use_i3;
int rvs;
int entries;
int stun;
int mn;
int mr;
};
/*
* Global configuration data
*/
struct hip_conf {
__u8 min_lifetime; /* values offered by the rvs */
__u8 max_lifetime;
__u8 reg_type_rvs;
__u8 lifetime; /* for registration with rvs. exponential lifetime */
__u8 reg_type; /*for registration with rvs. */
__u8 reg_types[MAX_REGISTRATION_TYPES];
__u8 n_reg_types;
__u32 cookie_difficulty; /* 2 raised to this power */
__u32 cookie_lifetime; /* valid 2^(life-32) seconds */
__u32 packet_timeout; /* seconds */
__u32 max_retries; /* retransmissions */
__u32 sa_lifetime; /* lifetime of SAs in seconds */
__u32 loc_lifetime; /* lifetime of locators in seconds */
char *preferred_hi; /* which HI to use */
__u8 send_hi_name; /* flag to include DI (FQDN) in HI */
__u8 dh_group; /* which DH group to propose in R1 */
__u32 dh_lifetime; /* seconds until DH expires */
__u32 r1_lifetime; /* seconds until an R1 is replaced */
__u32 failure_timeout; /* seconds to wait in state E_FAILED */
__u32 msl; /* max segment lifetime */
__u32 ual; /* seconds until unused SA expires */
__u16 esp_transforms[SUITE_ID_MAX]; /* ESP transforms proposed in R1 */
__u16 hip_transforms[SUITE_ID_MAX]; /* HIP transforms proposed in R1 */
char *log_filename; /* non-default pathname for log */
struct sockaddr_storage dht_server; /* address+port of DHT server */
struct sockaddr_storage dns_server; /* address of server w/HIP RRs */
__u8 disable_dns_lookups; /* T/F disable DNS lookups */
__u8 disable_notify; /* T/F disable sending NOTIFY packets */
__u8 disable_dns_thread; /* T/F disable DNS thread */
__u8 enable_bcast; /* T/F unicast packets from bcast LSI */
char *master_interface;
struct sockaddr_storage preferred; /* preferred address */
char *preferred_iface; /* preferred interface name */
char *outbound_iface; /* if mobile router */
__u8 save_known_identities; /* save known_host_id's on exit */
__u8 peer_certificate_required;
__u8 use_smartcard; /* use smartcard for hostid, RSA/DSA sign and X.509 certificate */
char *smartcard_pin; /* the pin */
__u8 use_local_known_identities; /* use local known_identities file or get it from a server such as Ldap */
char *cfg_serv_host; /* e.g. ldaphost if using ldap for config server*/
__u32 cfg_serv_port; /* e.g. ldap server port */
char *cfg_serv_basedn; /* e.g. ldap base dn */
char *cfg_serv_login_id; /* e.g. ldap binddn */
char *cfg_serv_login_pwd; /* e.g. ldap bindpw */
char conf_filename[255];
char my_hi_filename[255];
char known_hi_filename[255];
};
extern RSA *hip_rsa_new();
extern void hip_rsa_free(RSA *rsa);
/*
* Mobile router registration extension
*/
typedef enum{
CANCELLED = 0,
RESPONSE_SENT,
TIMED_OUT
} MR_STATES;
typedef struct _hip_proxy_ticket {
__u8 hmac_key[20];
__u16 hmac_key_index;
__u16 transform_type;
__u16 action;
__u16 lifetime;
__u8 hmac[20];
} hip_proxy_ticket;
typedef struct _hip_spi_nat {
hip_hit peer_hit;
struct sockaddr_storage peer_addr;
__u32 private_spi;
__u32 public_spi;
__u32 peer_spi;
hip_proxy_ticket ticket;
struct _hip_spi_nat *next;
} hip_spi_nat;
typedef struct _hip_mr_client {
hip_hit mn_hit;
struct sockaddr_storage mn_addr;
MR_STATES state;
hip_spi_nat *spi_nats;
} hip_mr_client;
#endif /* _HIP_TYPES_H_*/

View File

@ -0,0 +1,112 @@
/*
* Host Identity Protocol
* Copyright (C) 2002-04 the Boeing Company
*
* 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 2 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.
*
* hip_service.h
*
* Authors: Jeff Ahrenholz <jeffrey.m.ahrenholz@boeing.com>
*
* Definition of HIP Windows service thread functions.
*
*/
#ifdef __WIN32__
#include <winsock2.h>
#include <ws2tcpip.h>
#else
#include <sys/socket.h> /* struct sockaddr */
#endif
/*
* Globally-accessible functions
*/
/* Windows _beghinthread() uses different type than pthread_create() */
#ifdef __WIN32__
void hip_esp_output(void *arg);
void hip_esp_input(void *arg);
void hip_pfkey(void *arg);
void tunreader(void *arg);
void hip_dns(void *arg);
void hipd_main(void *arg);
void hip_netlink(void *arg);
void hip_status(void *arg);
void hip_mobile_router(void *arg);
extern int socketpair(int, int, int, int sv[2]);
#define RETNULL ;
#else
void *hip_esp_output(void *arg);
void *hip_esp_input(void *arg);
void *hip_pfkey(void *arg);
void *tunreader(void *arg);
void *hip_dns(void *arg);
void *hipd_main(void *arg);
void *hip_netlink(void *arg);
void *hip_status(void *arg);
void *hip_mobile_router(void *arg);
#define RETNULL NULL;
#endif
int init_esp_input(int family, int proto);
int main_loop(int argc, char **argv);
int str_to_addr(unsigned char *data, struct sockaddr *addr);
int pfkey_send_acquire(struct sockaddr *target);
/*
* Global definitions
*/
#ifndef CONFIG_HIP
#define CONFIG_HIP
#endif
#define DNS_PORT 53
#define HIP_DNS_SUFFIX ".hip"
extern __u64 g_tap_mac;
extern int g_state;
/*
* Macros from hip.h and elsewhere
*/
#if 0
/* get pointer to IP from a sockaddr
* useful for inet_ntop calls */
#define SA2IP(x) (((struct sockaddr*)x)->sa_family==AF_INET) ? \
(void*)&((struct sockaddr_in*)x)->sin_addr : \
(void*)&((struct sockaddr_in6*)x)->sin6_addr
/* get socket address length in bytes */
#define SALEN(x) (((struct sockaddr*)x)->sa_family==AF_INET) ? \
sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6)
/* get IP address length in bytes */
#define SAIPLEN(x) (((struct sockaddr*)x)->sa_family==AF_INET) ? 4 : 16
#endif
#define IS_LSI32(a) ((a & 0xFF) == 0x01)
/* from linux/include/linux/kernel.h */
#define NIPQUAD(addr) \
((unsigned char *)&addr)[0], \
((unsigned char *)&addr)[1], \
((unsigned char *)&addr)[2], \
((unsigned char *)&addr)[3]
#define NIP6(addr) \
ntohs((addr).s6_addr16[0]), \
ntohs((addr).s6_addr16[1]), \
ntohs((addr).s6_addr16[2]), \
ntohs((addr).s6_addr16[3]), \
ntohs((addr).s6_addr16[4]), \
ntohs((addr).s6_addr16[5]), \
ntohs((addr).s6_addr16[6]), \
ntohs((addr).s6_addr16[7])
#define TRUE 1
#define FALSE 0

View File

@ -0,0 +1,29 @@
/*
* Host Identity Protocol
* Copyright (C) 2002-06 the Boeing Company
*
* 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 2 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.
*
* hip_version.h
*
* Authors: Jeff Ahrenholz, <jeffrey.m.ahrenholz@boeing.com>
*
*
*/
#ifndef _HIP_VERSION_H_
#define _HIP_VERSION_H_
#define HIP_VERSION "@PACKAGE_VERSION@"
#define HIP_NAME "@PACKAGE_NAME@"
#endif /* !_HIP_VERSION_H_ */

39
src/include/hip/i3_hip.h Normal file
View File

@ -0,0 +1,39 @@
/*
* Interface with i3 and HIP for Hi3
* Author: (c) Andrei Gurtov, HIIT
* Licence: GPLv2
* Written: 3.4.2005
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <sys/types.h> /* basic system data types */
#include <sys/socket.h> /* basic socket definitions */
#include <sys/time.h> /* timeval{} for select() */
#include <errno.h>
#include <sys/utsname.h>
#include <time.h> /* timespec{} for pselect() */
#include <netinet/in.h> /* sockaddr_in{} and other Internet defns */
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
#include <netinet/udp.h>
#include <netinet/ip.h>
#include "i3_server/i3_matching.h"
#include "i3/i3.h"
#include "i3_client/i3_client_api.h"
#include "i3_client/i3_client_id.h"
#include "hip.h"
#define CFGFILE "i3-cfg-PL.xml"
//#define HI3_DEBUG
int cl_register_callback(unsigned short, void (*)(), void*);
int send_i3(__u8 *, int, hip_hit *, struct sockaddr*, struct sockaddr*);
void hip_handle_packet(struct msghdr* , int, __u16);
int i3_init(hip_hit*);
void init_id_fromstr(ID *, char *);
void print_hit(const hip_hit *);
void clean_i3();

117
src/include/hip/sc_utils.h Normal file
View File

@ -0,0 +1,117 @@
#ifndef SCUTILS_H
#define SCUTILS_H
#include <openssl/ssl.h>
#include <openssl/engine.h>
#include <opensc/opensc.h>
#include <opensc/pkcs15.h>
#define NAMELENGTH 256
#define BUFFERSIZE 1024
#define NUM_RETRIES 0
#define NUM_PING_RETRIES 3
#define MAX_PINSIZE 8
enum HTTP_REQUEST_TYPE {
HTTP_HEADER,
CERT_REQ,
IPSEC_SC_CONF,
IPSEC_SC_SECRETS,
IPSEC_TC_CONF,
IPSEC_TC_SECRETS
};
enum DATA_REQUEST_TYPE {
TCERT_FILE,
TCERT_KEY_FILE,
SCCERT_FILE,
IPSEC_CONF_FILE,
IPSEC_SECRETS_FILE,
SC_PIN,
VPN_SERVER,
HTTPS_SERVER,
IPSEC_CONF,
NETWORK_INTERFACE,
LDAP_UPDATE,
MY_HOST
};
enum IPSEC_ERRORS {
NO_DETECTED_ERROR=0,
NETWORK_ERROR,
CERT_ERROR_LOCAL,
CERT_READ_ERROR,
CERT_EXPIRED_LOCAL,
CERT_EXPIRED_REMOTE,
STALE_SA,
IPSEC_TO_PHYS_INT_ERROR,
NO_ISAKMP
};
struct vpn {
char addr[NAMELENGTH];
char gw[NAMELENGTH];
char subnet[NAMELENGTH];
char dn[NAMELENGTH];
};
void * my_malloc(const char *caller, size_t size);
void * my_calloc(const char *caller, size_t nmemb, size_t size);
void * my_realloc(const char *caller, void *ptr_old, size_t size);
void my_free(const char *caller, void *ptr);
void proc_config(char * conf_filename);
void print_options();
int tcp_connect();
int load_engine_fn(ENGINE *e, const char *engine_id,
const char **pre_cmds, int pre_num,
const char **post_cmds, int post_num);
ENGINE * engine_init(char *pin);
void engine_teardown(ENGINE *e);
int verify_callback(int preverify_ok, X509_STORE_CTX *x509_ctx);
EVP_PKEY * load_sc_pkey(const char *file, ENGINE *e, const char *pin);
SSL_CTX * ssl_ctx_init(ENGINE *e, const char *pin);
int send_bytes(SSL *ssl, int nbytes, char *ptr);
int recv_bytes(SSL *ssl, int nbytes, char *ptr);
char * msgrecv(SSL *ssl, int *nread);
int bio_setup( FILE * outputFile );
void bio_teardown();
char * make_message(int message_len, const char *fmt, ...);
char * read_file(char *fname, int *nread);
char * url_encode(char *string);
char * generate_request(int form);
char * parse_cert(char *input);
int write_file(char *data, char *fname);
int connect_card(struct sc_context *ctx, struct sc_card **cardp,
int reader_id, int slot_id);
int connect_card2(struct sc_context *ctx, struct sc_card **cardp,
int reader_id, int slot_id, int wait);
int read_sc_cert(struct sc_pkcs15_card *p15card, char *outfile, u8 *buf);
int verify_pin(struct sc_pkcs15_card *p15card, const char *pincode);
int check_files();
int remove_files();
void * get_data(int flag);
void put_data(int flag, void *data);
int getPlutoPID(char * plutoPID, int nTries);
int checkIPSecErrors(char * plutoPID);
int checkIPSecErrorLog();
int checkIPSecRuntime();
int checkIPSecInterface();
int checkIPSecIFConnections();
int pcscStart();
int pcscStatus();
int pcscStop();
int ipsecStart();
int ipsecStop();
int ipsecRestart();
int ipsecReplaceConnection(char * connName);
int ipsecRestartConnection(char * connName);
int ipsecDeleteConnection(char * connName);
int ipsecReattachConnection();
int isWirelessUp();
int isWirelessConfig();
int pingVPN();
int pingRA();
#endif

View File

@ -0,0 +1,392 @@
#include <sys/types.h>
#include <netinet/in.h>
#ifdef __BIG_ENDIAN__
static inline unsigned short csum_tcpudp_hip_nofold(unsigned long,
unsigned long,
unsigned short,
unsigned short);
static inline unsigned int csum_fold(unsigned int sum)
{
unsigned int tmp;
/* swap the two 16-bit halves of sum */
__asm__("rlwinm %0,%1,16,0,31" : "=r" (tmp) : "r" (sum));
/* if there is a carry from adding the two 16-bit halves,
it will carry from the lower half into the upper half,
giving us the correct sum in the upper half. */
sum = ~(sum + tmp) >> 16;
return sum;
}
static inline unsigned int csum_add(unsigned int csum, unsigned int addend)
{
csum += addend;
return csum + (csum < addend);
}
static inline unsigned int csum_sub(unsigned int csum, unsigned int addend)
{
return csum_add(csum, ~addend);
}
ushort checksum16(unsigned char* data, int len)
{
uint sum = 0;
if ((len & 1) == 0)
len = len >> 1;
else
len = (len >> 1) + 1;
while (len > 0) {
sum += *((ushort*)data);
data += sizeof(ushort);
len--;
}
sum = (sum >> 16) + (sum & 0xffff);
sum += (sum >> 16);
return(~sum);
}
static inline unsigned short csum_tcpudp_hip_nofold(unsigned long saddr,
unsigned long daddr,
unsigned short sum,
unsigned short hitMagic)
{
/* sum is assumed to be the folded complement, so get the sum back */
unsigned short ret = ~sum;
ret = ~csum_fold(csum_add(ret, hitMagic));
ret = csum_fold(csum_sub(ret,~csum_fold(csum_add(saddr,daddr))));
return ret;
}
static inline unsigned short ip_fast_csum(unsigned char * iph,
unsigned int ihl)
{
return checksum16(iph,ihl);
}
static inline unsigned short csum_hip_revert(unsigned long saddr,
unsigned long daddr,
unsigned short sum,
unsigned short hitMagic)
{
/* sum is assumed to be the folded complement, so get the sum back */
unsigned short ret = ~sum;
ret = ~csum_fold(csum_sub(ret, hitMagic));
ret = csum_fold(csum_add(ret,~csum_fold(csum_add(saddr,daddr))));
return ret;
}
#ifdef XXX_OBSOLETE?
/*
* computes the checksum of the TCP/UDP pseudo-header
* returns a 16-bit checksum, already complemented
*/
static inline unsigned short int csum_tcpudp_magic(unsigned long saddr,
unsigned long daddr,
unsigned short len,
unsigned short proto,
unsigned int sum)
{
return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));
}
#endif
#elif defined(__LITTLE_ENDIAN__)
/*
* This file contains a combination of:
* linux/include/asm-i386/checksum.h and
* linux/include/net/checksum.h from the Linux 2.6.8.1 kernel,
* plus HIP checksum modifications.
*
*/
/*
* INET An implementation of the TCP/IP protocol suite for the LINUX
* operating system. INET is implemented using the BSD Socket
* interface as the means of communication with the user level.
*
* Checksumming functions for IP, TCP, UDP and so on
*
* Authors: Jorge Cwik, <jorge@laser.satlink.net>
* Arnt Gulbrandsen, <agulbra@nvg.unit.no>
* Borrows very liberally from tcp.c and ip.c, see those
* files for more names.
*
* 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
* 2 of the License, or (at your option) any later version.
*/
#ifndef _CHECKSUM_H
#define _CHECKSUM_H
/*
* the following inlines are from linux/include/asm-i386/checksum.h
*/
/*
* This is a version of ip_compute_csum() optimized for IP headers,
* which always checksum on 4 octet boundaries.
*
* By Jorge Cwik <jorge@laser.satlink.net>, adapted for linux by
* Arnt Gulbrandsen.
*/
static inline unsigned short ip_fast_csum(unsigned char * iph,
unsigned int ihl)
{
unsigned int sum;
__asm__ __volatile__(
"movl (%1), %0 ;\n"
"subl $4, %2 ;\n"
"jbe 2f ;\n"
"addl 4(%1), %0 ;\n"
"adcl 8(%1), %0 ;\n"
"adcl 12(%1), %0 ;\n"
"1: adcl 16(%1), %0 ;\n"
"lea 4(%1), %1 ;\n"
"decl %2 ;\n"
"jne 1b ;\n"
"adcl $0, %0 ;\n"
"movl %0, %2 ;\n"
"shrl $16, %0 ;\n"
"addw %w2, %w0 ;\n"
"adcl $0, %0 ;\n"
"notl %0 ;\n"
"2: ;\n"
/* Since the input registers which are loaded with iph and ipl
are modified, we must also specify them as outputs, or gcc
will assume they contain their original values. */
: "=r" (sum), "=r" (iph), "=r" (ihl)
: "1" (iph), "2" (ihl)
: "memory");
return(sum);
}
/*
* Fold a partial checksum
*/
static inline unsigned int csum_fold(unsigned int sum)
{
__asm__(
"addl %1, %0 ;\n"
"adcl $0xffff, %0 ;\n"
: "=r" (sum)
: "r" (sum << 16), "0" (sum & 0xffff0000)
);
return (~sum) >> 16;
}
static inline unsigned long csum_tcpudp_nofold(unsigned long saddr,
unsigned long daddr,
unsigned short len,
unsigned short proto,
unsigned int sum)
{
__asm__(
"addl %1, %0 ;\n"
"adcl %2, %0 ;\n"
"adcl %3, %0 ;\n"
"adcl $0, %0 ;\n"
: "=r" (sum)
: "g" (daddr), "g"(saddr), "g"((ntohs(len)<<16)+proto*256), "0"(sum));
return sum;
}
/*
* computes the checksum of the TCP/UDP pseudo-header
* returns a 16-bit checksum, already complemented
*/
static inline unsigned short int csum_tcpudp_magic(unsigned long saddr,
unsigned long daddr,
unsigned short len,
unsigned short proto,
unsigned int sum)
{
return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));
}
#define _HAVE_ARCH_IPV6_CSUM
static __inline__ unsigned short int csum_ipv6_magic(struct in6_addr *saddr,
struct in6_addr *daddr,
__u32 len,
unsigned short proto,
unsigned int sum)
{
__asm__(
"addl 0(%1), %0 ;\n"
"adcl 4(%1), %0 ;\n"
"adcl 8(%1), %0 ;\n"
"adcl 12(%1), %0 ;\n"
"adcl 0(%2), %0 ;\n"
"adcl 4(%2), %0 ;\n"
"adcl 8(%2), %0 ;\n"
"adcl 12(%2), %0 ;\n"
"adcl %3, %0 ;\n"
"adcl %4, %0 ;\n"
"adcl $0, %0 ;\n"
: "=&r" (sum)
: "r" (saddr), "r" (daddr),
"r"(htonl(len)), "r"(htonl(proto)), "0"(sum));
return csum_fold(sum);
}
#endif
/*
* the following inlines are from linux/include/net/checksum.h
*/
static inline unsigned int csum_add(unsigned int csum, unsigned int addend)
{
csum += addend;
return csum + (csum < addend);
}
static inline unsigned int csum_sub(unsigned int csum, unsigned int addend)
{
return csum_add(csum, ~addend);
}
/*
* HIP checksum = tcp checksum + hitMagic - csum(saddr,daddr)
*/
static inline unsigned short csum_tcpudp_hip_nofold(unsigned long saddr,
unsigned long daddr,
unsigned short sum,
unsigned short hitMagic)
{
/* sum is assumed to be the folded complement, so get the sum back */
unsigned short ret = ~sum;
ret = ~csum_fold(csum_add(ret, hitMagic));
ret = csum_fold(csum_sub(ret,~csum_fold(csum_add(saddr,daddr))));
return ret;
}
static inline unsigned short csum_hip_revert(unsigned long saddr,
unsigned long daddr,
unsigned short sum,
unsigned short hitMagic)
{
/* sum is assumed to be the folded complement, so get the sum back */
unsigned short ret = ~sum;
ret = ~csum_fold(csum_sub(ret, hitMagic));
ret = csum_fold(csum_add(ret,~csum_fold(csum_add(saddr,daddr))));
return ret;
}
/*
* HIP checksum = tcp checksum + hitMagic - csum(saddr,daddr)
*/
static inline unsigned short csum_tcpudp_hip_nofold6(struct in6_addr *saddr,
struct in6_addr *daddr,
unsigned short sum,
unsigned short hitMagic)
{
int carry;
unsigned int csum;
/* sum is assumed to be the folded complement, so get the sum back */
unsigned short ret = ~sum;
/* First, sum saddr and daddr as done in csum_ipv6_magic() */
csum = saddr->__u6_addr.__u6_addr32[0];
carry = (csum < saddr->__u6_addr.__u6_addr32[0]);
csum += carry;
csum += saddr->__u6_addr.__u6_addr32[1];
carry = (csum < saddr->__u6_addr.__u6_addr32[1]);
csum += carry;
csum += saddr->__u6_addr.__u6_addr32[2];
carry = (csum < saddr->__u6_addr.__u6_addr32[2]);
csum += carry;
csum += saddr->__u6_addr.__u6_addr32[3];
carry = (csum < saddr->__u6_addr.__u6_addr32[3]);
csum += carry;
csum += daddr->__u6_addr.__u6_addr32[0];
carry = (csum < daddr->__u6_addr.__u6_addr32[0]);
csum += carry;
csum += daddr->__u6_addr.__u6_addr32[1];
carry = (csum < daddr->__u6_addr.__u6_addr32[1]);
csum += carry;
csum += daddr->__u6_addr.__u6_addr32[2];
carry = (csum < daddr->__u6_addr.__u6_addr32[2]);
csum += carry;
csum += daddr->__u6_addr.__u6_addr32[3];
carry = (csum < daddr->__u6_addr.__u6_addr32[3]);
csum += carry;
/* Next, add in the hitMagic and subtract saddr+daddr */
ret = ~csum_fold(csum_add(ret, hitMagic));
ret = csum_fold(csum_sub(ret,~csum_fold(csum)));
return ret;
}
static inline unsigned short csum_hip_revert6(struct in6_addr *saddr,
struct in6_addr *daddr,
unsigned short sum,
unsigned short hitMagic)
{
int carry;
unsigned int csum;
/* sum is assumed to be the folded complement, so get the sum back */
unsigned short ret = ~sum;
/* First, sum saddr and daddr as done in csum_ipv6_magic() */
csum = saddr->__u6_addr.__u6_addr32[0];
carry = (csum < saddr->__u6_addr.__u6_addr32[0]);
csum += carry;
csum += saddr->__u6_addr.__u6_addr32[1];
carry = (csum < saddr->__u6_addr.__u6_addr32[1]);
csum += carry;
csum += saddr->__u6_addr.__u6_addr32[2];
carry = (csum < saddr->__u6_addr.__u6_addr32[2]);
csum += carry;
csum += saddr->__u6_addr.__u6_addr32[3];
carry = (csum < saddr->__u6_addr.__u6_addr32[3]);
csum += carry;
csum += daddr->__u6_addr.__u6_addr32[0];
carry = (csum < daddr->__u6_addr.__u6_addr32[0]);
csum += carry;
csum += daddr->__u6_addr.__u6_addr32[1];
carry = (csum < daddr->__u6_addr.__u6_addr32[1]);
csum += carry;
csum += daddr->__u6_addr.__u6_addr32[2];
carry = (csum < daddr->__u6_addr.__u6_addr32[2]);
csum += carry;
csum += daddr->__u6_addr.__u6_addr32[3];
carry = (csum < daddr->__u6_addr.__u6_addr32[3]);
csum += carry;
/* Next, subtract hitMagic and add saddr+daddr */
ret = ~csum_fold(csum_sub(ret, hitMagic));
ret = csum_fold(csum_add(ret,~csum_fold(csum)));
return ret;
}
#endif

View File

@ -0,0 +1,15 @@
#ifndef __u8
#define __u8 unsigned char
#endif
#ifndef __uint8_t
#define __uint8_t unsigned char
#endif
#ifndef __u16
#define __u16 unsigned short
#endif
#ifndef __u32
#define __u32 unsigned int
#endif
#ifndef __u64
#define __u64 unsigned long long
#endif

View File

@ -0,0 +1,587 @@
/*
* This file contains a combination of:
* linux/include/asm-i386/checksum.h and
* linux/include/net/checksum.h from the Linux 2.6.8.1 kernel,
* plus HIP checksum modifications.
*
*/
/*
* INET An implementation of the TCP/IP protocol suite for the LINUX
* operating system. INET is implemented using the BSD Socket
* interface as the means of communication with the user level.
*
* Checksumming functions for IP, TCP, UDP and so on
*
* Authors: Jorge Cwik, <jorge@laser.satlink.net>
* Arnt Gulbrandsen, <agulbra@nvg.unit.no>
* Borrows very liberally from tcp.c and ip.c, see those
* files for more names.
*
* 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
* 2 of the License, or (at your option) any later version.
*/
#ifndef _CHECKSUM_H
#define _CHECKSUM_H
#ifndef __WIN32__
#include <asm/types.h>
#include <endian.h>
#include <netinet/in.h>
#else
#include <win32/types.h>
#include <ws2tcpip.h>
#endif /* __WIN32__ */
#ifdef __WIN32__
/* Windows' ws2tcpip.h has struct in6_addr with __u8 and __u16 members,
* but no __u32 as we need here for accumulation.
*/
struct my_in6_addr {
__u32 s6_addr32[4];
};
#endif
/*
* the following inlines are from linux/include/asm-i386/checksum.h
*/
/*
* This is a version of ip_compute_csum() optimized for IP headers,
* which always checksum on 4 octet boundaries.
*
* By Jorge Cwik <jorge@laser.satlink.net>, adapted for linux by
* Arnt Gulbrandsen.
*/
#ifdef __WIN32__
/* This isn't the 'fast' checksum, since the GCC inline ASM version is not
* available in Windows; this is the same code from hip_util.c */
static __inline unsigned short ip_fast_csum(unsigned char * iph,
unsigned int ihl)
{
__u16 checksum;
unsigned long sum = 0;
int count = ihl*4;
unsigned short *p = (unsigned short *)iph;
/*
* this checksum algorithm can be found
* in RFC 1071 section 4.1
*/
/* one's complement sum 16-bit words of data */
while (count > 1) {
sum += *p++;
count -= 2;
}
/* add left-over byte, if any */
if (count > 0)
sum += (unsigned char)*p;
/* Fold 32-bit sum to 16 bits */
while (sum>>16)
sum = (sum & 0xffff) + (sum >> 16);
/* take the one's complement of the sum */
checksum = (__u16)(~sum);
return(checksum);
}
#else
static inline unsigned short ip_fast_csum(unsigned char * iph,
unsigned int ihl)
{
unsigned int sum;
__asm__ __volatile__(
"movl (%1), %0 ;\n"
"subl $4, %2 ;\n"
"jbe 2f ;\n"
"addl 4(%1), %0 ;\n"
"adcl 8(%1), %0 ;\n"
"adcl 12(%1), %0 ;\n"
"1: adcl 16(%1), %0 ;\n"
"lea 4(%1), %1 ;\n"
"decl %2 ;\n"
"jne 1b ;\n"
"adcl $0, %0 ;\n"
"movl %0, %2 ;\n"
"shrl $16, %0 ;\n"
"addw %w2, %w0 ;\n"
"adcl $0, %0 ;\n"
"notl %0 ;\n"
"2: ;\n"
/* Since the input registers which are loaded with iph and ipl
are modified, we must also specify them as outputs, or gcc
will assume they contain their original values. */
: "=r" (sum), "=r" (iph), "=r" (ihl)
: "1" (iph), "2" (ihl)
: "memory");
return(sum);
}
#endif
/*
* Fold a partial checksum
*/
#ifdef __WIN32__
static __inline unsigned int csum_fold(unsigned int sum)
{
/* this is from hip_util.c - checksum_packet() */
/* Fold 32-bit sum to 16 bits */
while (sum>>16)
sum = (sum & 0xffff) + (sum >> 16);
/* take the one's complement of the sum */
return((__u16)~sum);
}
#else
static inline unsigned int csum_fold(unsigned int sum)
{
__asm__(
"addl %1, %0 ;\n"
"adcl $0xffff, %0 ;\n"
: "=r" (sum)
: "r" (sum << 16), "0" (sum & 0xffff0000)
);
return (~sum) >> 16;
}
#endif
#ifdef __WIN32__
static __inline unsigned int csum_add(unsigned int csum, unsigned int addend);
static __inline unsigned long csum_tcpudp_nofold(unsigned long saddr,
unsigned long daddr,
unsigned short len,
unsigned short proto,
unsigned int sum)
{
sum = csum_add(sum, saddr);
sum = csum_add(sum, daddr);
sum = csum_add(sum, (__u32)len);
sum = csum_add(sum, (__u32)proto);
return(sum);
}
#else
static inline unsigned long csum_tcpudp_nofold(unsigned long saddr,
unsigned long daddr,
unsigned short len,
unsigned short proto,
unsigned int sum)
{
__asm__(
"addl %1, %0 ;\n"
"adcl %2, %0 ;\n"
"adcl %3, %0 ;\n"
"adcl $0, %0 ;\n"
: "=r" (sum)
: "g" (daddr), "g"(saddr), "g"((ntohs(len)<<16)+proto*256), "0"(sum));
return sum;
}
#endif
/*
* computes the checksum of the TCP/UDP pseudo-header
* returns a 16-bit checksum, already complemented
*/
#ifdef __WIN32__
static __inline unsigned short int csum_tcpudp_magic(unsigned long saddr,
unsigned long daddr,
unsigned short len,
unsigned short proto,
unsigned int sum)
#else
static inline unsigned short int csum_tcpudp_magic(unsigned long saddr,
unsigned long daddr,
unsigned short len,
unsigned short proto,
unsigned int sum)
#endif
{
return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));
}
#ifndef __WIN32__
#define _HAVE_ARCH_IPV6_CSUM
static __inline__ unsigned short int csum_ipv6_magic(struct in6_addr *saddr,
struct in6_addr *daddr,
__u32 len,
unsigned short proto,
unsigned int sum)
{
__asm__(
"addl 0(%1), %0 ;\n"
"adcl 4(%1), %0 ;\n"
"adcl 8(%1), %0 ;\n"
"adcl 12(%1), %0 ;\n"
"adcl 0(%2), %0 ;\n"
"adcl 4(%2), %0 ;\n"
"adcl 8(%2), %0 ;\n"
"adcl 12(%2), %0 ;\n"
"adcl %3, %0 ;\n"
"adcl %4, %0 ;\n"
"adcl $0, %0 ;\n"
: "=&r" (sum)
: "r" (saddr), "r" (daddr),
"r"(htonl(len)), "r"(htonl(proto)), "0"(sum));
return csum_fold(sum);
}
#endif
/*
* the following inlines are from linux/include/net/checksum.h
*/
#ifdef __WIN32__
static __inline unsigned int csum_add(unsigned int csum, unsigned int addend)
#else
static inline unsigned int csum_add(unsigned int csum, unsigned int addend)
#endif
{
csum += addend;
return csum + (csum < addend);
}
#ifdef __WIN32__
static __inline unsigned int csum_sub(unsigned int csum, unsigned int addend)
#else
static inline unsigned int csum_sub(unsigned int csum, unsigned int addend)
#endif
{
return csum_add(csum, ~addend);
}
/*
* HIP checksum = tcp checksum + hitMagic - csum(saddr,daddr)
*/
#ifdef __WIN32__
static __inline unsigned short csum_tcpudp_hip_nofold(unsigned long saddr,
unsigned long daddr,
unsigned short sum,
unsigned short hitMagic)
#else
static inline unsigned short csum_tcpudp_hip_nofold(unsigned long saddr,
unsigned long daddr,
unsigned short sum,
unsigned short hitMagic)
#endif
{
/* sum is assumed to be the folded complement, so get the sum back */
unsigned short ret = ~sum;
ret = ~csum_fold(csum_add(ret, hitMagic));
ret = csum_fold(csum_sub(ret,~csum_fold(csum_add(saddr,daddr))));
return ret;
}
#ifdef __WIN32__
static __inline unsigned short csum_hip_revert(unsigned long saddr,
unsigned long daddr,
unsigned short sum,
unsigned short hitMagic)
#else
static inline unsigned short csum_hip_revert(unsigned long saddr,
unsigned long daddr,
unsigned short sum,
unsigned short hitMagic)
#endif
{
/* sum is assumed to be the folded complement, so get the sum back */
unsigned short ret = ~sum;
ret = ~csum_fold(csum_sub(ret, hitMagic));
ret = csum_fold(csum_add(ret,~csum_fold(csum_add(saddr,daddr))));
return ret;
}
/*
* HIP checksum = tcp checksum + hitMagic - csum(saddr,daddr)
*/
#ifdef __WIN32__
static __inline unsigned short csum_tcpudp_hip_nofold6(struct in6_addr *saddr1,
struct in6_addr *daddr1,
unsigned short sum,
unsigned short hitMagic)
{
int carry;
unsigned int csum;
/* sum is assumed to be the folded complement, so get the sum back */
unsigned short ret = ~sum;
/* Re-cast the struct since Windows has no 32-bit struct member. */
struct my_in6_addr *saddr = (struct my_in6_addr*)saddr1;
struct my_in6_addr *daddr = (struct my_in6_addr*)daddr1;
/* First, sum saddr and daddr as done in csum_ipv6_magic() */
csum = saddr->s6_addr32[0];
carry = (csum < saddr->s6_addr32[0]);
csum += carry;
csum += saddr->s6_addr32[1];
carry = (csum < saddr->s6_addr32[1]);
csum += carry;
csum += saddr->s6_addr32[2];
carry = (csum < saddr->s6_addr32[2]);
csum += carry;
csum += saddr->s6_addr32[3];
carry = (csum < saddr->s6_addr32[3]);
csum += carry;
csum += daddr->s6_addr32[0];
carry = (csum < daddr->s6_addr32[0]);
csum += carry;
csum += daddr->s6_addr32[1];
carry = (csum < daddr->s6_addr32[1]);
csum += carry;
csum += daddr->s6_addr32[2];
carry = (csum < daddr->s6_addr32[2]);
csum += carry;
csum += daddr->s6_addr32[3];
carry = (csum < daddr->s6_addr32[3]);
csum += carry;
/* Next, add in the hitMagic and subtract saddr+daddr */
ret = ~csum_fold(csum_add(ret, hitMagic));
ret = csum_fold(csum_sub(ret,~csum_fold(csum)));
return ret;
}
#else
static inline unsigned short csum_tcpudp_hip_nofold6(struct in6_addr *saddr,
struct in6_addr *daddr,
unsigned short sum,
unsigned short hitMagic)
{
int carry;
unsigned int csum;
/* sum is assumed to be the folded complement, so get the sum back */
unsigned short ret = ~sum;
/* First, sum saddr and daddr as done in csum_ipv6_magic() */
#ifdef __CYGWIN__
csum = saddr->__u6_addr.__u6_addr32[0];
carry = (csum < saddr->__u6_addr.__u6_addr32[0]);
csum += carry;
csum += saddr->__u6_addr.__u6_addr32[1];
carry = (csum < saddr->__u6_addr.__u6_addr32[1]);
csum += carry;
csum += saddr->__u6_addr.__u6_addr32[2];
carry = (csum < saddr->__u6_addr.__u6_addr32[2]);
csum += carry;
csum += saddr->__u6_addr.__u6_addr32[3];
carry = (csum < saddr->__u6_addr.__u6_addr32[3]);
csum += carry;
csum += daddr->__u6_addr.__u6_addr32[0];
carry = (csum < daddr->__u6_addr.__u6_addr32[0]);
csum += carry;
csum += daddr->__u6_addr.__u6_addr32[1];
carry = (csum < daddr->__u6_addr.__u6_addr32[1]);
csum += carry;
csum += daddr->__u6_addr.__u6_addr32[2];
carry = (csum < daddr->__u6_addr.__u6_addr32[2]);
csum += carry;
csum += daddr->__u6_addr.__u6_addr32[3];
carry = (csum < daddr->__u6_addr.__u6_addr32[3]);
csum += carry;
#else
csum = saddr->s6_addr32[0];
carry = (csum < saddr->s6_addr32[0]);
csum += carry;
csum += saddr->s6_addr32[1];
carry = (csum < saddr->s6_addr32[1]);
csum += carry;
csum += saddr->s6_addr32[2];
carry = (csum < saddr->s6_addr32[2]);
csum += carry;
csum += saddr->s6_addr32[3];
carry = (csum < saddr->s6_addr32[3]);
csum += carry;
csum += daddr->s6_addr32[0];
carry = (csum < daddr->s6_addr32[0]);
csum += carry;
csum += daddr->s6_addr32[1];
carry = (csum < daddr->s6_addr32[1]);
csum += carry;
csum += daddr->s6_addr32[2];
carry = (csum < daddr->s6_addr32[2]);
csum += carry;
csum += daddr->s6_addr32[3];
carry = (csum < daddr->s6_addr32[3]);
csum += carry;
#endif
/* Next, add in the hitMagic and subtract saddr+daddr */
ret = ~csum_fold(csum_add(ret, hitMagic));
ret = csum_fold(csum_sub(ret,~csum_fold(csum)));
return ret;
}
#endif
#ifdef __WIN32__
static __inline unsigned short csum_hip_revert6(struct in6_addr *saddr1,
struct in6_addr *daddr1,
unsigned short sum,
unsigned short hitMagic)
{
int carry;
unsigned int csum;
/* sum is assumed to be the folded complement, so get the sum back */
unsigned short ret = ~sum;
/* Re-cast the struct since Windows has no 32-bit struct member. */
struct my_in6_addr *saddr = (struct my_in6_addr*)saddr1;
struct my_in6_addr *daddr = (struct my_in6_addr*)daddr1;
/* First, sum saddr and daddr as done in csum_ipv6_magic() */
csum = saddr->s6_addr32[0];
carry = (csum < saddr->s6_addr32[0]);
csum += carry;
csum += saddr->s6_addr32[1];
carry = (csum < saddr->s6_addr32[1]);
csum += carry;
csum += saddr->s6_addr32[2];
carry = (csum < saddr->s6_addr32[2]);
csum += carry;
csum += saddr->s6_addr32[3];
carry = (csum < saddr->s6_addr32[3]);
csum += carry;
csum += daddr->s6_addr32[0];
carry = (csum < daddr->s6_addr32[0]);
csum += carry;
csum += daddr->s6_addr32[1];
carry = (csum < daddr->s6_addr32[1]);
csum += carry;
csum += daddr->s6_addr32[2];
carry = (csum < daddr->s6_addr32[2]);
csum += carry;
csum += daddr->s6_addr32[3];
carry = (csum < daddr->s6_addr32[3]);
csum += carry;
/* Next, subtract hitMagic and add saddr+daddr */
ret = ~csum_fold(csum_sub(ret, hitMagic));
ret = csum_fold(csum_add(ret,~csum_fold(csum)));
return ret;
}
#else
static inline unsigned short csum_hip_revert6(struct in6_addr *saddr,
struct in6_addr *daddr,
unsigned short sum,
unsigned short hitMagic)
{
int carry;
unsigned int csum;
/* sum is assumed to be the folded complement, so get the sum back */
unsigned short ret = ~sum;
/* First, sum saddr and daddr as done in csum_ipv6_magic() */
#ifdef __CYGWIN__
csum = saddr->__u6_addr.__u6_addr32[0];
carry = (csum < saddr->__u6_addr.__u6_addr32[0]);
csum += carry;
csum += saddr->__u6_addr.__u6_addr32[1];
carry = (csum < saddr->__u6_addr.__u6_addr32[1]);
csum += carry;
csum += saddr->__u6_addr.__u6_addr32[2];
carry = (csum < saddr->__u6_addr.__u6_addr32[2]);
csum += carry;
csum += saddr->__u6_addr.__u6_addr32[3];
carry = (csum < saddr->__u6_addr.__u6_addr32[3]);
csum += carry;
csum += daddr->__u6_addr.__u6_addr32[0];
carry = (csum < daddr->__u6_addr.__u6_addr32[0]);
csum += carry;
csum += daddr->__u6_addr.__u6_addr32[1];
carry = (csum < daddr->__u6_addr.__u6_addr32[1]);
csum += carry;
csum += daddr->__u6_addr.__u6_addr32[2];
carry = (csum < daddr->__u6_addr.__u6_addr32[2]);
csum += carry;
csum += daddr->__u6_addr.__u6_addr32[3];
carry = (csum < daddr->__u6_addr.__u6_addr32[3]);
csum += carry;
#else
csum = saddr->s6_addr32[0];
carry = (csum < saddr->s6_addr32[0]);
csum += carry;
csum += saddr->s6_addr32[1];
carry = (csum < saddr->s6_addr32[1]);
csum += carry;
csum += saddr->s6_addr32[2];
carry = (csum < saddr->s6_addr32[2]);
csum += carry;
csum += saddr->s6_addr32[3];
carry = (csum < saddr->s6_addr32[3]);
csum += carry;
csum += daddr->s6_addr32[0];
carry = (csum < daddr->s6_addr32[0]);
csum += carry;
csum += daddr->s6_addr32[1];
carry = (csum < daddr->s6_addr32[1]);
csum += carry;
csum += daddr->s6_addr32[2];
carry = (csum < daddr->s6_addr32[2]);
csum += carry;
csum += daddr->s6_addr32[3];
carry = (csum < daddr->s6_addr32[3]);
csum += carry;
#endif
/* Next, subtract hitMagic and add saddr+daddr */
ret = ~csum_fold(csum_sub(ret, hitMagic));
ret = csum_fold(csum_add(ret,~csum_fold(csum)));
return ret;
}
#endif
#endif

170
src/include/win32/ip.h Normal file
View File

@ -0,0 +1,170 @@
/*
* Host Identity Protocol
* Copyright (C) 2005 the Boeing Company
*
* 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 2 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.
*
* ip.h
*
* Authors: Jeff Ahrenholz <jeffrey.m.ahrenholz@boeing.com>
*
* Definitions for TCP/IP headers that are missing from Windows.
*
*/
#ifndef _HIP_IP_H_
#define _HIP_IP_H_
#include <ws2tcpip.h> /* this is required for the struct in6_addr's in
struct ip6_hdr */
#define IPVERSION 4
struct ip {
__u8 ip_hl:4, ip_v:4; /* MSVC requires these are char */
/*__u32 ip_hl:4; This will not work with MSVC.
__u32 ip_v:4;*/
__u8 ip_tos;
__u16 ip_len;
__u16 ip_id;
__u16 ip_off;
__u8 ip_ttl;
__u8 ip_p;
__u16 ip_sum;
union { /* allows use of struct ip or iphdr*/
struct in_addr ip_src;
__u32 saddr;
};
union {
struct in_addr ip_dst;
__u32 daddr;
};
};
/* allows use of struct ip or iphdr*/
#define iphdr ip
#define ihl ip_hl
struct udphdr {
/* __u16 uh_sport;
__u16 uh_dport; */
__u16 source;
__u16 dest;
__u16 uh_ulen;
__u16 check;
};
struct tcphdr {
/* __u16 th_sport;
__u16 th_dport; */
__u16 source;
__u16 dest;
__u32 th_seq;
__u32 th_ack;
__u8 th_x2:4, th_off:4;
__u8 th_flags;
__u16 th_win;
__u16 check;
__u16 th_urp;
};
/* from netinet/ip6.h */
struct ip6_hdr
{
union
{
struct ip6_hdrctl
{
__u32 ip6_un1_flow; /* 4 bits version, 8 bits TC,
20 bits flow-ID */
__u16 ip6_un1_plen; /* payload length */
__u8 ip6_un1_nxt; /* next header */
__u8 ip6_un1_hlim; /* hop limit */
} ip6_un1;
__u8 ip6_un2_vfc; /* 4 bits version, top 4 bits tclass */
} ip6_ctlun;
struct in6_addr ip6_src; /* source address */
struct in6_addr ip6_dst; /* destination address */
};
#define ip6_vfc ip6_ctlun.ip6_un2_vfc
#define ip6_flow ip6_ctlun.ip6_un1.ip6_un1_flow
#define ip6_plen ip6_ctlun.ip6_un1.ip6_un1_plen
#define ip6_nxt ip6_ctlun.ip6_un1.ip6_un1_nxt
#define ip6_hlim ip6_ctlun.ip6_un1.ip6_un1_hlim
#define ip6_hops ip6_ctlun.ip6_un1.ip6_un1_hlim
/* from netinet/icmp6.h */
struct icmp6_hdr
{
__u8 icmp6_type; /* type field */
__u8 icmp6_code; /* code field */
__u16 icmp6_cksum; /* checksum field */
union
{
__u32 icmp6_un_data32[1]; /* type-specific field */
__u16 icmp6_un_data16[2]; /* type-specific field */
__u8 icmp6_un_data8[4]; /* type-specific field */
} icmp6_dataun;
};
#define icmp6_data32 icmp6_dataun.icmp6_un_data32
#define icmp6_data16 icmp6_dataun.icmp6_un_data16
#define icmp6_data8 icmp6_dataun.icmp6_un_data8
#define icmp6_pptr icmp6_data32[0] /* parameter prob */
#define icmp6_mtu icmp6_data32[0] /* packet too big */
#define icmp6_id icmp6_data16[0] /* echo request/reply */
#define icmp6_seq icmp6_data16[1] /* echo request/reply */
#define icmp6_maxdelay icmp6_data16[0] /* mcast group membership */
#define ICMP6_DST_UNREACH 1
#define ICMP6_PACKET_TOO_BIG 2
#define ICMP6_TIME_EXCEEDED 3
#define ICMP6_PARAM_PROB 4
#define ICMP6_INFOMSG_MASK 0x80 /* all informational messages */
#define ICMP6_ECHO_REQUEST 128
#define ICMP6_ECHO_REPLY 129
#define ICMP6_MEMBERSHIP_QUERY 130
#define ICMP6_MEMBERSHIP_REPORT 131
#define ICMP6_MEMBERSHIP_REDUCTION 132
#define ND_ROUTER_SOLICIT 133
#define ND_ROUTER_ADVERT 134
#define ND_NEIGHBOR_SOLICIT 135
#define ND_NEIGHBOR_ADVERT 136
#define ND_REDIRECT 137
#if BYTE_ORDER == BIG_ENDIAN
#define ND_NA_FLAG_ROUTER 0x80000000
#define ND_NA_FLAG_SOLICITED 0x40000000
#define ND_NA_FLAG_OVERRIDE 0x20000000
#else /* BYTE_ORDER == LITTLE_ENDIAN */
#define ND_NA_FLAG_ROUTER 0x00000080
#define ND_NA_FLAG_SOLICITED 0x00000040
#define ND_NA_FLAG_OVERRIDE 0x00000020
#endif
struct nd_opt_hdr /* Neighbor discovery option header */
{
uint8_t nd_opt_type;
uint8_t nd_opt_len; /* in units of 8 octets */
/* followed by option specific data */
};
#define ND_OPT_SOURCE_LINKADDR 1
#define ND_OPT_TARGET_LINKADDR 2
#define ND_OPT_PREFIX_INFORMATION 3
#define ND_OPT_REDIRECTED_HEADER 4
#define ND_OPT_MTU 5
#define ND_OPT_RTR_ADV_INTERVAL 7
#define ND_OPT_HOME_AGENT_INFO 8
#endif /* _HIP_IP_H_ */

View File

@ -0,0 +1,92 @@
#ifndef __LINUX_NETLINK_H
#define __LINUX_NETLINK_H
#define NETLINK_ROUTE 0 /* Routing/device hook */
#define NETLINK_SKIP 1 /* Reserved for ENskip */
#define NETLINK_USERSOCK 2 /* Reserved for user mode socket protocols */
#define NETLINK_FIREWALL 3 /* Firewalling hook */
#define NETLINK_TCPDIAG 4 /* TCP socket monitoring */
#define NETLINK_NFLOG 5 /* netfilter/iptables ULOG */
#define NETLINK_ARPD 8
#define NETLINK_ROUTE6 11 /* af_inet6 route comm channel */
#define NETLINK_IP6_FW 13
#define NETLINK_DNRTMSG 14 /* DECnet routing messages */
#define NETLINK_TAPBASE 16 /* 16 to 31 are ethertap */
#define MAX_LINKS 32
#ifdef __WIN32__
typedef unsigned char sa_family_t;
#endif
struct sockaddr_nl
{
sa_family_t nl_family; /* AF_NETLINK */
unsigned short nl_pad; /* zero */
__u32 nl_pid; /* process pid */
__u32 nl_groups; /* multicast groups mask */
};
struct nlmsghdr
{
__u32 nlmsg_len; /* Length of message including header */
__u16 nlmsg_type; /* Message content */
__u16 nlmsg_flags; /* Additional flags */
__u32 nlmsg_seq; /* Sequence number */
__u32 nlmsg_pid; /* Sending process PID */
};
/* Flags values */
#define NLM_F_REQUEST 1 /* It is request message. */
#define NLM_F_MULTI 2 /* Multipart message, terminated by NLMSG_DONE */
#define NLM_F_ACK 4 /* Reply with ack, with zero or error code */
#define NLM_F_ECHO 8 /* Echo this request */
/* Modifiers to GET request */
#define NLM_F_ROOT 0x100 /* specify tree root */
#define NLM_F_MATCH 0x200 /* return all matching */
#define NLM_F_ATOMIC 0x400 /* atomic GET */
#define NLM_F_DUMP (NLM_F_ROOT|NLM_F_MATCH)
/* Modifiers to NEW request */
#define NLM_F_REPLACE 0x100 /* Override existing */
#define NLM_F_EXCL 0x200 /* Do not touch, if it exists */
#define NLM_F_CREATE 0x400 /* Create, if it does not exist */
#define NLM_F_APPEND 0x800 /* Add to end of list */
/*
4.4BSD ADD NLM_F_CREATE|NLM_F_EXCL
4.4BSD CHANGE NLM_F_REPLACE
True CHANGE NLM_F_CREATE|NLM_F_REPLACE
Append NLM_F_CREATE
Check NLM_F_EXCL
*/
#define NLMSG_ALIGNTO 4
#define NLMSG_ALIGN(len) ( ((len)+NLMSG_ALIGNTO-1) & ~(NLMSG_ALIGNTO-1) )
#define NLMSG_LENGTH(len) ((len)+NLMSG_ALIGN(sizeof(struct nlmsghdr)))
#define NLMSG_SPACE(len) NLMSG_ALIGN(NLMSG_LENGTH(len))
#define NLMSG_DATA(nlh) ((void*)(((char*)nlh) + NLMSG_LENGTH(0)))
#define NLMSG_NEXT(nlh,len) ((len) -= NLMSG_ALIGN((nlh)->nlmsg_len), \
(struct nlmsghdr*)(((char*)(nlh)) + NLMSG_ALIGN((nlh)->nlmsg_len)))
#define NLMSG_OK(nlh,len) ((len) > 0 && (nlh)->nlmsg_len >= sizeof(struct nlmsghdr) && \
(nlh)->nlmsg_len <= (len))
#define NLMSG_PAYLOAD(nlh,len) ((nlh)->nlmsg_len - NLMSG_SPACE((len)))
#define NLMSG_NOOP 0x1 /* Nothing. */
#define NLMSG_ERROR 0x2 /* Error */
#define NLMSG_DONE 0x3 /* End of a dump */
#define NLMSG_OVERRUN 0x4 /* Data lost */
struct nlmsgerr
{
int error;
struct nlmsghdr msg;
};
#define NET_MAJOR 36 /* Major 36 is reserved for networking */
#endif /* __LINUX_NETLINK_H */

View File

@ -0,0 +1,76 @@
/*
* TAP-Win32 -- A kernel driver to provide virtual tap device functionality
* on Windows. Originally derived from the CIPE-Win32
* project by Damion K. Wilson, with extensive modifications by
* James Yonan.
*
* All source code which derives from the CIPE-Win32 project is
* Copyright (C) Damion K. Wilson, 2003, and is released under the
* GPL version 2 (see below).
*
* All other source code is Copyright (C) James Yonan, 2003-2004,
* and is released under the GPL version 2 (see below).
*
* 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 2 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 (see the file COPYING included with this
* distribution); if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
//===============================================
// This file is included both by OpenVPN and
// the TAP-Win32 driver and contains definitions
// common to both.
//===============================================
//=============
// TAP IOCTLs
//=============
#define TAP_CONTROL_CODE(request,method) \
CTL_CODE (FILE_DEVICE_UNKNOWN, request, method, FILE_ANY_ACCESS)
#define TAP_IOCTL_GET_MAC TAP_CONTROL_CODE (1, METHOD_BUFFERED)
#define TAP_IOCTL_GET_VERSION TAP_CONTROL_CODE (2, METHOD_BUFFERED)
#define TAP_IOCTL_GET_MTU TAP_CONTROL_CODE (3, METHOD_BUFFERED)
#define TAP_IOCTL_GET_INFO TAP_CONTROL_CODE (4, METHOD_BUFFERED)
#define TAP_IOCTL_CONFIG_POINT_TO_POINT TAP_CONTROL_CODE (5, METHOD_BUFFERED)
#define TAP_IOCTL_SET_MEDIA_STATUS TAP_CONTROL_CODE (6, METHOD_BUFFERED)
#define TAP_IOCTL_CONFIG_DHCP_MASQ TAP_CONTROL_CODE (7, METHOD_BUFFERED)
#define TAP_IOCTL_GET_LOG_LINE TAP_CONTROL_CODE (8, METHOD_BUFFERED)
#define TAP_IOCTL_CONFIG_DHCP_SET_OPT TAP_CONTROL_CODE (9, METHOD_BUFFERED)
//=================
// Registry keys
//=================
#define ADAPTER_KEY "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}"
#define NETWORK_CONNECTIONS_KEY "SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}"
//======================
// Filesystem prefixes
//======================
#define USERMODEDEVICEDIR "\\\\.\\Global\\"
#define SYSDEVICEDIR "\\Device\\"
#define USERDEVICEDIR "\\DosDevices\\Global\\"
#define TAPSUFFIX ".tap"
//=========================================================
// TAP_COMPONENT_ID -- This string defines the TAP driver
// type -- different component IDs can reside in the system
// simultaneously.
//=========================================================
#define TAP_COMPONENT_ID "tap0801"

484
src/include/win32/pfkeyv2.h Normal file
View File

@ -0,0 +1,484 @@
/* PF_KEY user interface, this is defined by rfc2367 so
* do not make arbitrary modifications or else this header
* file will not be compliant.
*/
#ifndef _LINUX_PFKEY2_H
#define _LINUX_PFKEY2_H
#ifdef __MACOSX__
#define uint8_t unsigned char
#define uint16_t unsigned short
#define uint32_t unsigned int
#define uint64_t unsigned long long
#endif
#define PF_KEY_V2 2
#define PFKEYV2_REVISION 199806L
struct sadb_msg {
uint8_t sadb_msg_version;
uint8_t sadb_msg_type;
uint8_t sadb_msg_errno;
uint8_t sadb_msg_satype;
uint16_t sadb_msg_len;
uint16_t sadb_msg_reserved;
uint32_t sadb_msg_seq;
uint32_t sadb_msg_pid;
}
#ifdef __WIN32__
;
#else
__attribute__((packed));
#endif
/* sizeof(struct sadb_msg) == 16 */
struct sadb_ext {
uint16_t sadb_ext_len;
uint16_t sadb_ext_type;
}
#ifdef __WIN32__
;
#else
__attribute__((packed));
#endif
/* sizeof(struct sadb_ext) == 4 */
struct sadb_sa {
uint16_t sadb_sa_len;
uint16_t sadb_sa_exttype;
uint32_t sadb_sa_spi;
uint8_t sadb_sa_replay;
uint8_t sadb_sa_state;
uint8_t sadb_sa_auth;
uint8_t sadb_sa_encrypt;
uint32_t sadb_sa_flags;
}
#ifdef __WIN32__
;
#else
__attribute__((packed));
#endif
/* sizeof(struct sadb_sa) == 16 */
struct sadb_lifetime {
uint16_t sadb_lifetime_len;
uint16_t sadb_lifetime_exttype;
uint32_t sadb_lifetime_allocations;
uint64_t sadb_lifetime_bytes;
uint64_t sadb_lifetime_addtime;
uint64_t sadb_lifetime_usetime;
}
#ifdef __WIN32__
;
#else
__attribute__((packed));
#endif
/* sizeof(struct sadb_lifetime) == 32 */
struct sadb_address {
uint16_t sadb_address_len;
uint16_t sadb_address_exttype;
uint8_t sadb_address_proto;
uint8_t sadb_address_prefixlen;
uint16_t sadb_address_reserved;
}
#ifdef __WIN32__
;
#else
__attribute__((packed));
#endif
/* sizeof(struct sadb_address) == 8 */
struct sadb_key {
uint16_t sadb_key_len;
uint16_t sadb_key_exttype;
uint16_t sadb_key_bits;
uint16_t sadb_key_reserved;
}
#ifdef __WIN32__
;
#else
__attribute__((packed));
#endif
/* sizeof(struct sadb_key) == 8 */
struct sadb_ident {
uint16_t sadb_ident_len;
uint16_t sadb_ident_exttype;
uint16_t sadb_ident_type;
uint16_t sadb_ident_reserved;
uint64_t sadb_ident_id;
}
#ifdef __WIN32__
;
#else
__attribute__((packed));
#endif
/* sizeof(struct sadb_ident) == 16 */
struct sadb_sens {
uint16_t sadb_sens_len;
uint16_t sadb_sens_exttype;
uint32_t sadb_sens_dpd;
uint8_t sadb_sens_sens_level;
uint8_t sadb_sens_sens_len;
uint8_t sadb_sens_integ_level;
uint8_t sadb_sens_integ_len;
uint32_t sadb_sens_reserved;
}
#ifdef __WIN32__
;
#else
__attribute__((packed));
#endif
/* sizeof(struct sadb_sens) == 16 */
/* followed by:
uint64_t sadb_sens_bitmap[sens_len];
uint64_t sadb_integ_bitmap[integ_len]; */
struct sadb_prop {
uint16_t sadb_prop_len;
uint16_t sadb_prop_exttype;
uint8_t sadb_prop_replay;
uint8_t sadb_prop_reserved[3];
}
#ifdef __WIN32__
;
#else
__attribute__((packed));
#endif
/* sizeof(struct sadb_prop) == 8 */
/* followed by:
struct sadb_comb sadb_combs[(sadb_prop_len +
sizeof(uint64_t) - sizeof(struct sadb_prop)) /
sizeof(strut sadb_comb)]; */
struct sadb_comb {
uint8_t sadb_comb_auth;
uint8_t sadb_comb_encrypt;
uint16_t sadb_comb_flags;
uint16_t sadb_comb_auth_minbits;
uint16_t sadb_comb_auth_maxbits;
uint16_t sadb_comb_encrypt_minbits;
uint16_t sadb_comb_encrypt_maxbits;
uint32_t sadb_comb_reserved;
uint32_t sadb_comb_soft_allocations;
uint32_t sadb_comb_hard_allocations;
uint64_t sadb_comb_soft_bytes;
uint64_t sadb_comb_hard_bytes;
uint64_t sadb_comb_soft_addtime;
uint64_t sadb_comb_hard_addtime;
uint64_t sadb_comb_soft_usetime;
uint64_t sadb_comb_hard_usetime;
}
#ifdef __WIN32__
;
#else
__attribute__((packed));
#endif
/* sizeof(struct sadb_comb) == 72 */
struct sadb_supported {
uint16_t sadb_supported_len;
uint16_t sadb_supported_exttype;
uint32_t sadb_supported_reserved;
}
#ifdef __WIN32__
;
#else
__attribute__((packed));
#endif
/* sizeof(struct sadb_supported) == 8 */
/* followed by:
struct sadb_alg sadb_algs[(sadb_supported_len +
sizeof(uint64_t) - sizeof(struct sadb_supported)) /
sizeof(struct sadb_alg)]; */
struct sadb_alg {
uint8_t sadb_alg_id;
uint8_t sadb_alg_ivlen;
uint16_t sadb_alg_minbits;
uint16_t sadb_alg_maxbits;
uint16_t sadb_alg_reserved;
}
#ifdef __WIN32__
;
#else
__attribute__((packed));
#endif
/* sizeof(struct sadb_alg) == 8 */
struct sadb_spirange {
uint16_t sadb_spirange_len;
uint16_t sadb_spirange_exttype;
uint32_t sadb_spirange_min;
uint32_t sadb_spirange_max;
uint32_t sadb_spirange_reserved;
}
#ifdef __WIN32__
;
#else
__attribute__((packed));
#endif
/* sizeof(struct sadb_spirange) == 16 */
struct sadb_x_kmprivate {
uint16_t sadb_x_kmprivate_len;
uint16_t sadb_x_kmprivate_exttype;
u_int32_t sadb_x_kmprivate_reserved;
}
#ifdef __WIN32__
;
#else
__attribute__((packed));
#endif
/* sizeof(struct sadb_x_kmprivate) == 8 */
struct sadb_x_sa2 {
uint16_t sadb_x_sa2_len;
uint16_t sadb_x_sa2_exttype;
uint8_t sadb_x_sa2_mode;
uint8_t sadb_x_sa2_reserved1;
uint16_t sadb_x_sa2_reserved2;
uint32_t sadb_x_sa2_sequence;
uint32_t sadb_x_sa2_reqid;
}
#ifdef __WIN32__
;
#else
__attribute__((packed));
#endif
/* sizeof(struct sadb_x_sa2) == 16 */
struct sadb_x_policy {
uint16_t sadb_x_policy_len;
uint16_t sadb_x_policy_exttype;
uint16_t sadb_x_policy_type;
uint8_t sadb_x_policy_dir;
uint8_t sadb_x_policy_reserved;
uint32_t sadb_x_policy_id;
uint32_t sadb_x_policy_priority;
}
#ifdef __WIN32__
;
#else
__attribute__((packed));
#endif
/* sizeof(struct sadb_x_policy) == 16 */
struct sadb_x_ipsecrequest {
uint16_t sadb_x_ipsecrequest_len;
uint16_t sadb_x_ipsecrequest_proto;
uint8_t sadb_x_ipsecrequest_mode;
uint8_t sadb_x_ipsecrequest_level;
uint16_t sadb_x_ipsecrequest_reserved1;
uint32_t sadb_x_ipsecrequest_reqid;
uint32_t sadb_x_ipsecrequest_reserved2;
}
#ifdef __WIN32__
;
#else
__attribute__((packed));
#endif
/* sizeof(struct sadb_x_ipsecrequest) == 16 */
/* This defines the TYPE of Nat Traversal in use. Currently only one
* type of NAT-T is supported, draft-ietf-ipsec-udp-encaps-06
*/
struct sadb_x_nat_t_type {
uint16_t sadb_x_nat_t_type_len;
uint16_t sadb_x_nat_t_type_exttype;
uint8_t sadb_x_nat_t_type_type;
uint8_t sadb_x_nat_t_type_reserved[3];
}
#ifdef __WIN32__
;
#else
__attribute__((packed));
#endif
/* sizeof(struct sadb_x_nat_t_type) == 8 */
/* Pass a NAT Traversal port (Source or Dest port) */
struct sadb_x_nat_t_port {
uint16_t sadb_x_nat_t_port_len;
uint16_t sadb_x_nat_t_port_exttype;
uint16_t sadb_x_nat_t_port_port;
uint16_t sadb_x_nat_t_port_reserved;
}
#ifdef __WIN32__
;
#else
__attribute__((packed));
#endif
/* sizeof(struct sadb_x_nat_t_port) == 8 */
#ifdef CONFIG_HIP
struct sadb_seqno {
uint16_t sadb_seqno_len;
uint16_t sadb_seqno_exttype;
uint32_t sadb_seqno;
};
struct sadb_lsi {
uint16_t sadb_lsi_len;
uint16_t sadb_lsi_exttype;
uint32_t sadb_lsi;
};
struct sadb_hit {
uint16_t sadb_hit_len;
uint16_t sadb_hit_exttype;
uint16_t sadb_hit;
uint16_t sadb_hit_reserved;
}
#ifdef __WIN32__
;
#else
__attribute__((packed));
#endif
#endif /* CONFIG_HIP */
/* Message types */
#define SADB_RESERVED 0
#define SADB_GETSPI 1
#define SADB_UPDATE 2
#define SADB_ADD 3
#define SADB_DELETE 4
#define SADB_GET 5
#define SADB_ACQUIRE 6
#define SADB_REGISTER 7
#define SADB_EXPIRE 8
#define SADB_FLUSH 9
#define SADB_DUMP 10
#define SADB_X_PROMISC 11
#define SADB_X_PCHANGE 12
#define SADB_X_SPDUPDATE 13
#define SADB_X_SPDADD 14
#define SADB_X_SPDDELETE 15
#define SADB_X_SPDGET 16
#define SADB_X_SPDACQUIRE 17
#define SADB_X_SPDDUMP 18
#define SADB_X_SPDFLUSH 19
#define SADB_X_SPDSETIDX 20
#define SADB_X_SPDEXPIRE 21
#define SADB_X_SPDDELETE2 22
#define SADB_X_NAT_T_NEW_MAPPING 23
#ifdef CONFIG_HIP
#define SADB_GETSEQ 24
#define SADB_GETLSI 25
#define SADB_READDRESS 26
#define SADB_HIP_ACQUIRE 27
#define SADB_HIP_ADD 28
#define SADB_MAX 29
#else
#define SADB_MAX 23
#endif
/* Security Association flags */
#define SADB_SAFLAGS_PFS 1
#define SADB_SAFLAGS_NOECN 0x80000000
/* Security Association states */
#define SADB_SASTATE_LARVAL 0
#define SADB_SASTATE_MATURE 1
#define SADB_SASTATE_DYING 2
#define SADB_SASTATE_DEAD 3
#define SADB_SASTATE_MAX 3
/* Security Association types */
#define SADB_SATYPE_UNSPEC 0
#define SADB_SATYPE_AH 2
#define SADB_SATYPE_ESP 3
#define SADB_SATYPE_RSVP 5
#define SADB_SATYPE_OSPFV2 6
#define SADB_SATYPE_RIPV2 7
#define SADB_SATYPE_MIP 8
#define SADB_X_SATYPE_IPCOMP 9
/*
#ifdef CONFIG_HIP
*/
#define SADB_X_SATYPE_HIP 10
#define SADB_SATYPE_MAX 10
/*
#else
#define SADB_SATYPE_MAX 9
#endif
*/
/* Authentication algorithms */
#define SADB_AALG_NONE 0
#define SADB_AALG_MD5HMAC 2
#define SADB_AALG_SHA1HMAC 3
#define SADB_X_AALG_SHA2_256HMAC 5
#define SADB_X_AALG_SHA2_384HMAC 6
#define SADB_X_AALG_SHA2_512HMAC 7
#define SADB_X_AALG_RIPEMD160HMAC 8
#define SADB_X_AALG_NULL 251 /* kame */
#define SADB_AALG_MAX 251
/* Encryption algorithms */
#define SADB_EALG_NONE 0
#define SADB_EALG_DESCBC 2
#define SADB_EALG_3DESCBC 3
#define SADB_X_EALG_CASTCBC 6
#define SADB_X_EALG_BLOWFISHCBC 7
#define SADB_EALG_NULL 11
#define SADB_X_EALG_AESCBC 12
#define SADB_EALG_MAX 253 /* last EALG */
/* private allocations should use 249-255 (RFC2407) */
#define SADB_X_EALG_SERPENTCBC 252 /* draft-ietf-ipsec-ciph-aes-cbc-00 */
#define SADB_X_EALG_TWOFISHCBC 253 /* draft-ietf-ipsec-ciph-aes-cbc-00 */
/* Compression algorithms */
#define SADB_X_CALG_NONE 0
#define SADB_X_CALG_OUI 1
#define SADB_X_CALG_DEFLATE 2
#define SADB_X_CALG_LZS 3
#define SADB_X_CALG_LZJH 4
#define SADB_X_CALG_MAX 4
/* Extension Header values */
#define SADB_EXT_RESERVED 0
#define SADB_EXT_SA 1
#define SADB_EXT_LIFETIME_CURRENT 2
#define SADB_EXT_LIFETIME_HARD 3
#define SADB_EXT_LIFETIME_SOFT 4
#define SADB_EXT_ADDRESS_SRC 5
#define SADB_EXT_ADDRESS_DST 6
#define SADB_EXT_ADDRESS_PROXY 7
#define SADB_EXT_KEY_AUTH 8
#define SADB_EXT_KEY_ENCRYPT 9
#define SADB_EXT_IDENTITY_SRC 10
#define SADB_EXT_IDENTITY_DST 11
#define SADB_EXT_SENSITIVITY 12
#define SADB_EXT_PROPOSAL 13
#define SADB_EXT_SUPPORTED_AUTH 14
#define SADB_EXT_SUPPORTED_ENCRYPT 15
#define SADB_EXT_SPIRANGE 16
#define SADB_X_EXT_KMPRIVATE 17
#define SADB_X_EXT_POLICY 18
#define SADB_X_EXT_SA2 19
/* The next four entries are for setting up NAT Traversal */
#define SADB_X_EXT_NAT_T_TYPE 20
#define SADB_X_EXT_NAT_T_SPORT 21
#define SADB_X_EXT_NAT_T_DPORT 22
#define SADB_X_EXT_NAT_T_OA 23
#ifdef CONFIG_HIP
#define SADB_EXT_SEQNO 24
#define SADB_EXT_LSI 25
#define SADB_EXT_HIT 26
#define SADB_EXT_MAX 26
#else
#define SADB_EXT_MAX 23
#endif
/* Identity Extension values */
#define SADB_IDENTTYPE_RESERVED 0
#define SADB_IDENTTYPE_PREFIX 1
#define SADB_IDENTTYPE_FQDN 2
#define SADB_IDENTTYPE_USERFQDN 3
#define SADB_IDENTTYPE_MAX 3
#endif /* !(_LINUX_PFKEY2_H) */

View File

@ -0,0 +1,543 @@
#ifndef __LINUX_RTNETLINK_H
#define __LINUX_RTNETLINK_H
#ifdef __MACOSX__
#define __s8 char
#define __s16 short
#define __s32 int
#define __s64 long long
#endif
#include "netlink.h"
#define RTNL_DEBUG 1
/****
* Routing/neighbour discovery messages.
****/
/* Types of messages */
#define RTM_BASE 0x10
#define RTM_NEWLINK (RTM_BASE+0)
#define RTM_DELLINK (RTM_BASE+1)
#define RTM_GETLINK (RTM_BASE+2)
#define RTM_NEWADDR (RTM_BASE+4)
#define RTM_DELADDR (RTM_BASE+5)
#define RTM_GETADDR (RTM_BASE+6)
#define RTM_NEWROUTE (RTM_BASE+8)
#define RTM_DELROUTE (RTM_BASE+9)
#define RTM_GETROUTE (RTM_BASE+10)
#define RTM_NEWNEIGH (RTM_BASE+12)
#define RTM_DELNEIGH (RTM_BASE+13)
#define RTM_GETNEIGH (RTM_BASE+14)
#define RTM_NEWRULE (RTM_BASE+16)
#define RTM_DELRULE (RTM_BASE+17)
#define RTM_GETRULE (RTM_BASE+18)
#define RTM_NEWQDISC (RTM_BASE+20)
#define RTM_DELQDISC (RTM_BASE+21)
#define RTM_GETQDISC (RTM_BASE+22)
#define RTM_NEWTCLASS (RTM_BASE+24)
#define RTM_DELTCLASS (RTM_BASE+25)
#define RTM_GETTCLASS (RTM_BASE+26)
#define RTM_NEWTFILTER (RTM_BASE+28)
#define RTM_DELTFILTER (RTM_BASE+29)
#define RTM_GETTFILTER (RTM_BASE+30)
#define RTM_MAX (RTM_BASE+31)
/*
Generic structure for encapsulation optional route information.
It is reminiscent of sockaddr, but with sa_family replaced
with attribute type.
*/
struct rtattr
{
unsigned short rta_len;
unsigned short rta_type;
};
/* Macros to handle rtattributes */
#define RTA_ALIGNTO 4
#define RTA_ALIGN(len) ( ((len)+RTA_ALIGNTO-1) & ~(RTA_ALIGNTO-1) )
#define RTA_OK(rta,len) ((len) > 0 && (rta)->rta_len >= sizeof(struct rtattr) && \
(rta)->rta_len <= (len))
#define RTA_NEXT(rta,attrlen) ((attrlen) -= RTA_ALIGN((rta)->rta_len), \
(struct rtattr*)(((char*)(rta)) + RTA_ALIGN((rta)->rta_len)))
#define RTA_LENGTH(len) (RTA_ALIGN(sizeof(struct rtattr)) + (len))
#define RTA_SPACE(len) RTA_ALIGN(RTA_LENGTH(len))
#define RTA_DATA(rta) ((void*)(((char*)(rta)) + RTA_LENGTH(0)))
#define RTA_PAYLOAD(rta) ((int)((rta)->rta_len) - RTA_LENGTH(0))
/******************************************************************************
* Definitions used in routing table administation.
****/
struct rtmsg
{
unsigned char rtm_family;
unsigned char rtm_dst_len;
unsigned char rtm_src_len;
unsigned char rtm_tos;
unsigned char rtm_table; /* Routing table id */
unsigned char rtm_protocol; /* Routing protocol; see below */
unsigned char rtm_scope; /* See below */
unsigned char rtm_type; /* See below */
unsigned rtm_flags;
};
/* rtm_type */
enum
{
RTN_UNSPEC,
RTN_UNICAST, /* Gateway or direct route */
RTN_LOCAL, /* Accept locally */
RTN_BROADCAST, /* Accept locally as broadcast,
send as broadcast */
RTN_ANYCAST, /* Accept locally as broadcast,
but send as unicast */
RTN_MULTICAST, /* Multicast route */
RTN_BLACKHOLE, /* Drop */
RTN_UNREACHABLE, /* Destination is unreachable */
RTN_PROHIBIT, /* Administratively prohibited */
RTN_THROW, /* Not in this table */
RTN_NAT, /* Translate this address */
RTN_XRESOLVE, /* Use external resolver */
};
#define RTN_MAX RTN_XRESOLVE
/* rtm_protocol */
#define RTPROT_UNSPEC 0
#define RTPROT_REDIRECT 1 /* Route installed by ICMP redirects;
not used by current IPv4 */
#define RTPROT_KERNEL 2 /* Route installed by kernel */
#define RTPROT_BOOT 3 /* Route installed during boot */
#define RTPROT_STATIC 4 /* Route installed by administrator */
/* Values of protocol >= RTPROT_STATIC are not interpreted by kernel;
they just passed from user and back as is.
It will be used by hypothetical multiple routing daemons.
Note that protocol values should be standardized in order to
avoid conflicts.
*/
#define RTPROT_GATED 8 /* Apparently, GateD */
#define RTPROT_RA 9 /* RDISC/ND router advertisments */
#define RTPROT_MRT 10 /* Merit MRT */
#define RTPROT_ZEBRA 11 /* Zebra */
#define RTPROT_BIRD 12 /* BIRD */
#define RTPROT_DNROUTED 13 /* DECnet routing daemon */
/* rtm_scope
Really it is not scope, but sort of distance to the destination.
NOWHERE are reserved for not existing destinations, HOST is our
local addresses, LINK are destinations, located on directly attached
link and UNIVERSE is everywhere in the Universe.
Intermediate values are also possible f.e. interior routes
could be assigned a value between UNIVERSE and LINK.
*/
enum rt_scope_t
{
RT_SCOPE_UNIVERSE=0,
/* User defined values */
RT_SCOPE_SITE=200,
RT_SCOPE_LINK=253,
RT_SCOPE_HOST=254,
RT_SCOPE_NOWHERE=255
};
/* rtm_flags */
#define RTM_F_NOTIFY 0x100 /* Notify user of route change */
#define RTM_F_CLONED 0x200 /* This route is cloned */
#define RTM_F_EQUALIZE 0x400 /* Multipath equalizer: NI */
/* Reserved table identifiers */
enum rt_class_t
{
RT_TABLE_UNSPEC=0,
/* User defined values */
RT_TABLE_DEFAULT=253,
RT_TABLE_MAIN=254,
RT_TABLE_LOCAL=255
};
#define RT_TABLE_MAX RT_TABLE_LOCAL
/* Routing message attributes */
enum rtattr_type_t
{
RTA_UNSPEC,
RTA_DST,
RTA_SRC,
RTA_IIF,
RTA_OIF,
RTA_GATEWAY,
RTA_PRIORITY,
RTA_PREFSRC,
RTA_METRICS,
RTA_MULTIPATH,
RTA_PROTOINFO,
RTA_FLOW,
RTA_CACHEINFO
};
#define RTA_MAX RTA_CACHEINFO
#define RTM_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct rtmsg))))
#define RTM_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct rtmsg))
/* RTM_MULTIPATH --- array of struct rtnexthop.
*
* "struct rtnexthop" describres all necessary nexthop information,
* i.e. parameters of path to a destination via this nextop.
*
* At the moment it is impossible to set different prefsrc, mtu, window
* and rtt for different paths from multipath.
*/
struct rtnexthop
{
unsigned short rtnh_len;
unsigned char rtnh_flags;
unsigned char rtnh_hops;
int rtnh_ifindex;
};
/* rtnh_flags */
#define RTNH_F_DEAD 1 /* Nexthop is dead (used by multipath) */
#define RTNH_F_PERVASIVE 2 /* Do recursive gateway lookup */
#define RTNH_F_ONLINK 4 /* Gateway is forced on link */
/* Macros to handle hexthops */
#define RTNH_ALIGNTO 4
#define RTNH_ALIGN(len) ( ((len)+RTNH_ALIGNTO-1) & ~(RTNH_ALIGNTO-1) )
#define RTNH_OK(rtnh,len) ((rtnh)->rtnh_len >= sizeof(struct rtnexthop) && \
((int)(rtnh)->rtnh_len) <= (len))
#define RTNH_NEXT(rtnh) ((struct rtnexthop*)(((char*)(rtnh)) + RTNH_ALIGN((rtnh)->rtnh_len)))
#define RTNH_LENGTH(len) (RTNH_ALIGN(sizeof(struct rtnexthop)) + (len))
#define RTNH_SPACE(len) RTNH_ALIGN(RTNH_LENGTH(len))
#define RTNH_DATA(rtnh) ((struct rtattr*)(((char*)(rtnh)) + RTNH_LENGTH(0)))
/* RTM_CACHEINFO */
struct rta_cacheinfo
{
__u32 rta_clntref;
__u32 rta_lastuse;
__s32 rta_expires;
__u32 rta_error;
__u32 rta_used;
#define RTNETLINK_HAVE_PEERINFO 1
__u32 rta_id;
__u32 rta_ts;
__u32 rta_tsage;
};
/* RTM_METRICS --- array of struct rtattr with types of RTAX_* */
enum
{
RTAX_UNSPEC,
#define RTAX_UNSPEC RTAX_UNSPEC
RTAX_LOCK,
#define RTAX_LOCK RTAX_LOCK
RTAX_MTU,
#define RTAX_MTU RTAX_MTU
RTAX_WINDOW,
#define RTAX_WINDOW RTAX_WINDOW
RTAX_RTT,
#define RTAX_RTT RTAX_RTT
RTAX_RTTVAR,
#define RTAX_RTTVAR RTAX_RTTVAR
RTAX_SSTHRESH,
#define RTAX_SSTHRESH RTAX_SSTHRESH
RTAX_CWND,
#define RTAX_CWND RTAX_CWND
RTAX_ADVMSS,
#define RTAX_ADVMSS RTAX_ADVMSS
RTAX_REORDERING,
#define RTAX_REORDERING RTAX_REORDERING
};
#define RTAX_MAX RTAX_REORDERING
/*********************************************************
* Interface address.
****/
struct ifaddrmsg
{
unsigned char ifa_family;
unsigned char ifa_prefixlen; /* The prefix length */
unsigned char ifa_flags; /* Flags */
unsigned char ifa_scope; /* See above */
int ifa_index; /* Link index */
};
enum
{
IFA_UNSPEC,
IFA_ADDRESS,
IFA_LOCAL,
IFA_LABEL,
IFA_BROADCAST,
IFA_ANYCAST,
IFA_CACHEINFO
};
#define IFA_MAX IFA_CACHEINFO
/* ifa_flags */
#define IFA_F_SECONDARY 0x01
#define IFA_F_DEPRECATED 0x20
#define IFA_F_TENTATIVE 0x40
#define IFA_F_PERMANENT 0x80
struct ifa_cacheinfo
{
__s32 ifa_prefered;
__s32 ifa_valid;
};
#define IFA_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ifaddrmsg))))
#define IFA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ifaddrmsg))
/*
Important comment:
IFA_ADDRESS is prefix address, rather than local interface address.
It makes no difference for normally configured broadcast interfaces,
but for point-to-point IFA_ADDRESS is DESTINATION address,
local address is supplied in IFA_LOCAL attribute.
*/
/**************************************************************
* Neighbour discovery.
****/
struct ndmsg
{
unsigned char ndm_family;
unsigned char ndm_pad1;
unsigned short ndm_pad2;
int ndm_ifindex; /* Link index */
__u16 ndm_state;
__u8 ndm_flags;
__u8 ndm_type;
};
enum
{
NDA_UNSPEC,
NDA_DST,
NDA_LLADDR,
NDA_CACHEINFO
};
#define NDA_MAX NDA_CACHEINFO
#define NDA_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ndmsg))))
#define NDA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ndmsg))
/*
* Neighbor Cache Entry Flags
*/
#define NTF_PROXY 0x08 /* == ATF_PUBL */
#define NTF_ROUTER 0x80
/*
* Neighbor Cache Entry States.
*/
#define NUD_INCOMPLETE 0x01
#define NUD_REACHABLE 0x02
#define NUD_STALE 0x04
#define NUD_DELAY 0x08
#define NUD_PROBE 0x10
#define NUD_FAILED 0x20
/* Dummy states */
#define NUD_NOARP 0x40
#define NUD_PERMANENT 0x80
#define NUD_NONE 0x00
struct nda_cacheinfo
{
__u32 ndm_confirmed;
__u32 ndm_used;
__u32 ndm_updated;
__u32 ndm_refcnt;
};
/****
* General form of address family dependent message.
****/
struct rtgenmsg
{
unsigned char rtgen_family;
};
/*****************************************************************
* Link layer specific messages.
****/
/* struct ifinfomsg
* passes link level specific information, not dependent
* on network protocol.
*/
struct ifinfomsg
{
unsigned char ifi_family;
unsigned char __ifi_pad;
unsigned short ifi_type; /* ARPHRD_* */
int ifi_index; /* Link index */
unsigned ifi_flags; /* IFF_* flags */
unsigned ifi_change; /* IFF_* change mask */
};
enum
{
IFLA_UNSPEC,
IFLA_ADDRESS,
IFLA_BROADCAST,
IFLA_IFNAME,
IFLA_MTU,
IFLA_LINK,
IFLA_QDISC,
IFLA_STATS,
IFLA_COST,
#define IFLA_COST IFLA_COST
IFLA_PRIORITY,
#define IFLA_PRIORITY IFLA_PRIORITY
IFLA_MASTER,
#define IFLA_MASTER IFLA_MASTER
IFLA_WIRELESS, /* Wireless Extension event - see wireless.h */
#define IFLA_WIRELESS IFLA_WIRELESS
};
#define IFLA_MAX IFLA_WIRELESS
#define IFLA_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ifinfomsg))))
#define IFLA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ifinfomsg))
/* ifi_flags.
IFF_* flags.
The only change is:
IFF_LOOPBACK, IFF_BROADCAST and IFF_POINTOPOINT are
more not changeable by user. They describe link media
characteristics and set by device driver.
Comments:
- Combination IFF_BROADCAST|IFF_POINTOPOINT is invalid
- If neiher of these three flags are set;
the interface is NBMA.
- IFF_MULTICAST does not mean anything special:
multicasts can be used on all not-NBMA links.
IFF_MULTICAST means that this media uses special encapsulation
for multicast frames. Apparently, all IFF_POINTOPOINT and
IFF_BROADCAST devices are able to use multicasts too.
*/
/* IFLA_LINK.
For usual devices it is equal ifi_index.
If it is a "virtual interface" (f.e. tunnel), ifi_link
can point to real physical interface (f.e. for bandwidth calculations),
or maybe 0, what means, that real media is unknown (usual
for IPIP tunnels, when route to endpoint is allowed to change)
*/
/*****************************************************************
* Traffic control messages.
****/
struct tcmsg
{
unsigned char tcm_family;
unsigned char tcm__pad1;
unsigned short tcm__pad2;
int tcm_ifindex;
__u32 tcm_handle;
__u32 tcm_parent;
__u32 tcm_info;
};
enum
{
TCA_UNSPEC,
TCA_KIND,
TCA_OPTIONS,
TCA_STATS,
TCA_XSTATS,
TCA_RATE,
};
#define TCA_MAX TCA_RATE
#define TCA_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct tcmsg))))
#define TCA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct tcmsg))
/* SUMMARY: maximal rtattr understood by kernel */
#define RTATTR_MAX RTA_MAX
/* RTnetlink multicast groups */
#define RTMGRP_LINK 1
#define RTMGRP_NOTIFY 2
#define RTMGRP_NEIGH 4
#define RTMGRP_TC 8
#define RTMGRP_IPV4_IFADDR 0x10
#define RTMGRP_IPV4_MROUTE 0x20
#define RTMGRP_IPV4_ROUTE 0x40
#define RTMGRP_IPV6_IFADDR 0x100
#define RTMGRP_IPV6_MROUTE 0x200
#define RTMGRP_IPV6_ROUTE 0x400
#define RTMGRP_DECnet_IFADDR 0x1000
#define RTMGRP_DECnet_ROUTE 0x4000
#endif /* __LINUX_RTNETLINK_H */

27
src/include/win32/types.h Normal file
View File

@ -0,0 +1,27 @@
/*
* Host Identity Protocol
* Copyright (C) 2002-05 the Boeing Company
*
* Replacement for asm/types.h
*/
typedef unsigned char __u8;
typedef unsigned short __u16;
typedef unsigned int __u32;
typedef signed int __s32;
typedef unsigned __int64 __u64;
/* mostly for PFKEY */
typedef char * caddr_t;
typedef unsigned char uint8_t;
typedef unsigned char u_int8_t;
typedef unsigned short uint16_t;
typedef unsigned short u_int16_t;
typedef unsigned int uint32_t;
typedef unsigned int u_int32_t;
typedef unsigned __int64 uint64_t;
typedef unsigned __int64 u_int64_t;

1
src/linux/deb/conffiles Normal file
View File

@ -0,0 +1 @@
/usr/local/etc/hip/known_host_identities.xml

18
src/linux/deb/control.in Normal file
View File

@ -0,0 +1,18 @@
Package: openhip
Version: @PACKAGE_VERSION@
Section: Networking
Priority: optional
Architecture: i386
Essential: no
Depends: libxml2, openssl
Installed-Size: 404
Maintainer: OpenHIP Developers [openhip-developers@lists.sourceforge.net]
Source: openhip
Provides: openhip
Description: OpenHIP for running the Host Identity Protocol in Linux user space. .
OpenHIP is a free, open-source implementation of the Host Identity Protocol (HIP). HIP is being developed within the Internet Engineering Task Force (IETF) and the Internet Research Task Force (IRTF) to study and experiment with HIP and related protocols.
.
HIP is a specific proposal to decouple network identity from network location in the Internet protocol stack. Historically, IP addresses have served both functions. This dual use of IP addresses is becoming problematic, and there have been many research efforts aimed at studying the decoupling of identifier and locator in the network stack. HIP is a specific proposal that uses public/private key pairs as the host identifiers.
.
More information can be found at:
<URL:http://www.openhip.org>

55
src/linux/deb/makedeb.sh Executable file
View File

@ -0,0 +1,55 @@
#!/bin/sh
#
# (c)2007 the Boeing Company
#
# makedeb.sh
# Author: Jeff Ahrenholz <jeffrey.m.ahrenholz@boeing.com>
#
# simple script to generate a deb package
#
#!/bin/sh
# assume we are running in src/linux/debian
MYDIR=$PWD
SRC=../..
# build HIP code
echo Building HIP binaries...
cd $SRC/..
./bootstrap.sh && ./configure && make
# get version number and remove quotes
HIPVER=`grep define\ HIP_VER src/include/hip/hip_version.h | awk {'gsub(/"/,a,$3); print $3'};`
# use this one for version number without quotes (float)
#HIPVER=`grep define\ HIP_VER src/include/hip/hip_version.h | awk {'print $3'};`
echo Detected version $HIPVER
echo Collecting files for data.tar.gz...
cd $MYDIR
mkdir tmp
mkdir tmp/DEBIAN
cd tmp
mkdir -p usr/local/sbin
mkdir -p usr/local/etc/hip
mkdir -p usr/share/doc/openhip-$HIPVER
cp -p ${PWD}/${SRC}/../hip usr/local/sbin
cp -p ${PWD}/${SRC}/../hitgen usr/local/sbin
cp -p ${PWD}/${SRC}/../../conf/known_host_identities.xml usr/local/etc/hip
cp -p ${PWD}/${SRC}/../../AUTHORS usr/share/doc/openhip-$HIPVER
cp -p ${PWD}/${SRC}/../../README usr/share/doc/openhip-$HIPVER
cp -p ${PWD}/${SRC}/../../LICENSE usr/share/doc/openhip-$HIPVER
find usr -type f -exec md5sum {} \; > ./DEBIAN/md5sums
echo Collecting control files...
cd $MYDIR
cp -p control tmp/DEBIAN
cp -p conffiles tmp/DEBIAN
cp -p postinst tmp/DEBIAN
chmod +x tmp/DEBIAN/postinst
echo Generating DEB file...
cd $MYDIR
dpkg-deb -b tmp openhip_${HIPVER}_i386.deb

5
src/linux/deb/postinst Normal file
View File

@ -0,0 +1,5 @@
#!/bin/sh
/usr/local/sbin/hitgen -conf -file /usr/local/etc/hip/hip.conf
/usr/local/sbin/hitgen -noinput -file /usr/local/etc/hip/my_host_identities.xml
mkdir -p /usr/local/var/log /usr/local/var/run

View File

@ -0,0 +1,28 @@
/*
* Host Identity Protocol
* Copyright (C) 2002-06 the Boeing Company
*
* 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 2 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.
*
* hip_linux_main.c
*
* Authors: Jeff Ahrenholz <jeffrey.m.ahrenholz@boeing.com>
*
* Stub program for Linux kernel version, calls main_loop().
*
*/
extern int main_loop(int argc, char **argv);
int main(int argc, char **argv)
{
return(main_loop(argc, argv));
}

454
src/linux/hip_linux_umh.c Normal file
View File

@ -0,0 +1,454 @@
/*
* Host Identity Protocol
* Copyright (C) 2004-06 the Boeing Company
*
* 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 2 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.
*
* hip_umh.c
*
* Authors: Jeff Ahrenholz <jeffrey.m.ahrenholz@boeing.com>
*
* User-mode HIP main program and initialization code.
* Multiple threads are spawned that perform the actual work.
*/
/*
* Style: KNF where possible, K&R style braces around control structures
* Style: indent using tabs-- multi-line continuation 4 spaces
* Style: no tabs in middle of lines
* Style: this code authored with tabstop=8
*/
#include <stdio.h> /* stderr, stdout */
#include <unistd.h> /* chdir() */
#include <pthread.h> /* pthread_create() */
#include <sys/time.h> /* gettimeofday() */
#include <sys/errno.h> /* errno */
#include <sys/ioctl.h> /* ioctl() */
#include <fcntl.h> /* open() */
#ifdef __MACOSX__
#include <sys/socket.h>
#include <netinet/in_systm.h>
#include <netinet/in.h>
#include <arpa/inet.h> /* inet_addr() */
#include <string.h> /* strerror() */
#include <netdb.h> /* inet_pton() */
#include <openssl/rand.h> /* RAND_seed() */
#include <net/if.h> /* TAP support */
#else
#include <linux/socket.h> /* AF_UNIX, SOCK_RAW, etc */
#include <netinet/in.h> /* in_addr_t, etc */
#include <arpa/inet.h> /* inet_addr() */
#include <string.h> /* strerror() */
#include <netdb.h> /* inet_pton() */
#include <openssl/rand.h> /* RAND_seed() */
#include <linux/if.h> /* TAP support */
#include <linux/if_tun.h> /* TAP support */
#endif
#include <hip/hip_version.h>
#include <hip/hip_service.h>
#include <hip/hip_types.h>
#include <hip/hip_funcs.h>
#include <hip/hip_globals.h>
#include <hip/hip_usermode.h>
#include <hip/hip_sadb.h>
extern int devname_to_index(char *dev, __u64 *mac);
extern int add_address_to_iface(struct sockaddr *addr, int plen, int if_index);
extern int set_link_params(char *dev, int mtu);
extern void add_local_hip_nameserver(__u32 ip);
extern int get_preferred_lsi(struct sockaddr *lsi);
extern int is_dns_thread_disabled();
extern int is_mobile_router();
/*
* Globals
*/
extern int tapfd;
extern int s_esp, s_esp_udp, s_esp6;
extern int s_udp;
int g_state;
char tap_dev_name[16];
/*
* print_hip_service_usage()
*
* Print parameters to the hip_service executable
*/
void print_hip_service_usage()
{
printf("%s v%s User-mode HIP\n", HIP_NAME, HIP_VERSION);
printf("Usage: hip [option]\n");
printf("Where option is one of the following:\n");
printf(" \t\t(No arguments defined at present)\n");
printf(" ...\tRemaining arguments are passed to hipd\n");
printf("\n");
}
int init_tap()
{
#ifndef __MACOSX__
struct ifreq ifr;
int err;
#endif
int tap;
printf("init_tap()\n");
/* Open TAP device */
/* XXX note: for FreeBSD, should execute ifconfig before this open */
#ifdef __MACOSX__
if ((tap = open("/dev/tap0", O_RDWR)) < 0) {
#else
if ((tap = open("/dev/net/tun", O_RDWR)) < 0) {
#endif
printf("Opening TAP device failed. Do you have the correct ");
printf("module loaded (modprobe tun)?\n");
return(-1);
}
#ifndef __MACOSX__
/* setup address */
memset(&ifr, 0, sizeof(ifr));
ifr.ifr_flags = IFF_TAP; /* TAP device */
ifr.ifr_flags |= IFF_NO_PI; /* Do not provide packet information */
sprintf(ifr.ifr_name, "hip0");
/* set TAP-32 status to connected */
if ((err = ioctl(tap, TUNSETIFF, (void*)&ifr)) < 0) {
close(tap);
printf("Error setting TAP parameters.\n");
return(-1);
}
strncpy(tap_dev_name, ifr.ifr_name, sizeof(tap_dev_name));
#else
strcpy(tap_dev_name,"tap0");
#endif
printf("Using TAP device %s.\n", tap_dev_name);
/* The netlink socket is not available yet, so setup
* of the tap address occurs later in post_init_tap().
*/
return tap;
}
void post_init_tap()
{
int if_index;
struct sockaddr_storage addr;
#ifdef __MACOSX__
__u32 taplsi;
char buff[255];
#endif
memset(&addr, 0, sizeof(struct sockaddr_storage));
addr.ss_family = AF_INET;
/* this performs the equivalent of:
* system("/sbin/ip addr add 1.0.0.1/8 broadcast 1.255.255.255 dev hip0")
* system("/sbin/ip link set hip0 mtu 1400");
* system("/sbin/ip link set hip0 up");
*/
/* Get the index and MAC address of the TAP
*/
post_init_tap_retry:
g_tap_mac = 0; /* MAC is needed for building eth hdrs in esp_input */
if_index = devname_to_index(tap_dev_name, &g_tap_mac);
if (if_index < 0) {
/* sometimes the TAP interface takes a second to come up */
printf("Waiting for TAP device %s to become ready...\n",
tap_dev_name);
usleep(50000);
goto post_init_tap_retry;
}
#ifdef __MACOSX__ /* I do not know why the tap driver will not take the ioctl
so, do things the "hard" way. */
taplsi = get_preferred_lsi(SA(&addr));
sprintf(buff,"/sbin/ifconfig %s %u.%u.%u.%u netmask 255.0.0.0 broadcast 1.255.255.255 up",tap_dev_name, NIPQUAD(LSI4((struct sockaddr *)&addr)));
printf("cmd = %s\n",buff);
system(buff);
#else
/* Add the 1.x.x.x LSI address to the TAP interface
*/
get_preferred_lsi(SA(&addr));
if (add_address_to_iface(SA(&addr), 8, if_index) < 0) {
printf("Error setting TAP address for %s.\n", tap_dev_name);
}
#endif
/* Set the link MTU and flag link UP
*/
#ifdef SMA_CRAWLER
if (set_link_params(tap_dev_name, 1500) < 0) {
#else
if (set_link_params(tap_dev_name, 1400) < 0) {
#endif
printf("Error setting TAP link MTU, up for %s\n", tap_dev_name);
}
#ifndef __MACOSX__
/* Add the 2001::10/28 HIT to the TAP (must occur after link is up)
*/
addr.ss_family = AF_INET6;
get_preferred_lsi(SA(&addr));
if (add_address_to_iface(SA(&addr), 28, if_index) < 0) {
printf("Error setting IPv6 TAP address for %s.\n",tap_dev_name); }
#endif /* __MACOSX__ */
/* Set the nameserver by adding 1.x.x.x to /etc/resolv.conf
*/
if (!is_dns_thread_disabled())
add_local_hip_nameserver(LSI4(&addr));
}
/*
* init_udp()
*
* Open and bind a UDP socket to HIP_ESP_UDP_PORT
*
* This socket is only defined to avoid ICMP errors 'Host unreachable :
* port unreachable'
* All the traffic is handled through the RAW socket.
*
*/
int init_udp()
{
int s, err;
struct sockaddr *local_addr;
struct sockaddr_storage local_addr_s;
__u16 port = HIP_ESP_UDP_PORT ;
local_addr = (struct sockaddr*) &local_addr_s;
if ((s = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
printf("init_udp(): socket() error\n");
printf("error: (%d) %s\n", errno, strerror(errno));
return(-1);
}
memset(local_addr, 0, sizeof(struct sockaddr_storage));
local_addr->sa_family = AF_INET;
((struct sockaddr_in*)local_addr)->sin_port = htons (port);
((struct sockaddr_in*)local_addr)->sin_addr.s_addr = INADDR_ANY;
if ((err = bind(s, local_addr, SALEN(local_addr))) < 0) {
printf("init_udp(): bind() error\n");
printf("error: (%d) %s\n", errno, strerror(errno));
return(-1);
}
return(s);
}
/*
* init_hip()
*
* HIP Windows service initialization. Start all of the threads.
*/
void init_hip(int ac, char **av)
{
pthread_t tunreader_thrd, esp_output_thrd, esp_input_thrd;
pthread_t pfkey_thrd, hipd_thrd, dns_thrd, status_thrd;
#ifdef MOBILE_ROUTER
pthread_t mr_thrd;
#endif /* MOBILE_ROUTER */
pthread_t keepalive_thrd, hip_keepalive_thrd;
char hipd_args[255];
int i;
char timestr[26];
struct timeval time1;
printf("init_hip()\n");
/* get arguments for hipd */
memset(hipd_args, 0, sizeof(hipd_args));
if (ac > 0)
ac--, av++;
i = 0;
while (ac > 0) {
// printf("adding arg: %s\n", *av);
if (i > 0) /* add a space between parameters */
hipd_args[i++] = ' ';
snprintf(&hipd_args[i], sizeof(hipd_args) - i, "%s", *av);
i += strlen(*av);
av++, ac--;
}
init_crypto();
hip_sadb_init();
g_state = 0;
/*
* Kernel helpers
*/
if (pthread_create(&pfkey_thrd, NULL, hip_pfkey, NULL)) {
printf("Error creating PFKEY thread.\n");
exit(-1);
}
if (pthread_create(&status_thrd, NULL, hip_status, NULL)) {
printf("Error creating status thread.\n");
exit(-1);
}
/*
* HIP daemon
*/
if (pthread_create(&hipd_thrd, NULL, hipd_main, &hipd_args)) {
printf("Error creating HIP daemon thread.\n");
exit(-1);
}
/*
* tap device
*/
if ((tapfd = init_tap()) > 0) {
printf("Initialized TAP device.\n");
} else {
printf("Error initializing TAP device.\n");
exit(-1);
}
if (pthread_create(&tunreader_thrd, NULL, tunreader, NULL)) {
printf("Error creating tunreader thread.\n");
exit(-1);
}
/*
* ESP handlers
*/
if (pthread_create(&esp_output_thrd, NULL, hip_esp_output, NULL)) {
printf("Error creating ESP output thread.\n");
exit(-1);
}
if ((s_esp = init_esp_input(AF_INET, IPPROTO_ESP)) < 0) {
printf("Error creating IPv4 ESP input socket.\n");
exit(-1);
}
#ifndef __MACOSX__
if ((s_esp_udp = init_esp_input(AF_INET, IPPROTO_UDP)) < 0) {
printf("Error creating IPv4 ESP-UDP input socket.\n");
exit(-1);
}
if ((s_esp6 = init_esp_input(AF_INET6, IPPROTO_ESP)) < 0) {
printf("Error creating IPv6 ESP input socket.\n");
exit(-1);
}
#endif
#ifndef __MACOSX__
/* Socket only used to indicate that UDP port
* HIP_ESP_OVER_UDP is 'reachable' */
if ((s_udp = init_udp()) < 0) {
printf("Error creating UDP socket.\n");
exit(-1);
}
#endif
if (pthread_create(&esp_input_thrd, NULL, hip_esp_input, NULL)) {
printf("Error creating ESP input thread.\n");
exit(-1);
}
#ifdef SMA_CRAWLER
hip_sleep(1); /* Wait a sec for config */
#endif /* SMA_CRAWLER */
if (!is_dns_thread_disabled()) {
/* XXX hip.conf may not be loaded yet */
if (pthread_create(&dns_thrd, NULL, hip_dns, NULL)) {
printf("Error creating DNS thread.\n");
exit(-1);
}
}
#ifdef MOBILE_ROUTER
if (is_mobile_router()) {
/* XXX command-line opts may not be loaded yet */
pthread_mutex_init(&hip_mr_client_mutex, NULL);
if (pthread_create(&mr_thrd, NULL, hip_mobile_router, NULL)) {
printf("Error creating Mobile Router thread.\n");
exit(-1);
}
}
#endif /* MOBILE_ROUTER */
/*
* Thread to handle keep-alives for UDP-ESP sockets
*/
if (pthread_create(&keepalive_thrd, NULL, udp_esp_keepalive, NULL)) {
printf("Error creating ESP keepalive thread.\n");
exit(-1);
}
/*
* Thread to handle keep-alives for UDP-HIP tunnels
*/
if (pthread_create(&hip_keepalive_thrd, NULL, udp_hip_keepalive, NULL)) {
printf("Error creating HIP keepalive thread.\n");
exit(-1);
}
hip_sleep(1); /* allow thread start before printing message */
gettimeofday(&time1, NULL);
ctime_r(&time1.tv_sec, timestr);
timestr[strlen(timestr)-1] = 0;
printf("%s HIP threads initialization completed.\n", timestr);
/*
* Wait for all threads to complete
*/
while (g_state == 0) {
hip_sleep(1);
}
pthread_join(hipd_thrd, NULL); /* hipd should exit first */
hip_sadb_deinit();
pthread_exit((void *) 0);
}
/******* MAIN ROUTINES *******/
/*
* main()
*
* Main command-line routine.
*/
int main (int argc, char **argv)
{
int rc;
/*
if (freopen("hip_ipsec_error.log", "a", stderr) == NULL)
return;
if (freopen("hip_ipsec.log", "a", stdout) == NULL)
return;
init_hip(ac, av);
*/
argv++, argc--;
while (argc > 0) {
rc = 0;
if (strstr("-v-q-d-r1-o-p-nr-t-u", *argv)) {
argv--, argc++;
goto start_hip;
} else {
print_hip_service_usage();
exit(0);
}
return(0);
} /* end while */
start_hip:
init_hip(argc, argv);
return(0);
}

66
src/linux/openhip.spec.in Normal file
View File

@ -0,0 +1,66 @@
%define version @PACKAGE_VERSION@
Name: openhip
License: GPLv2
Group: System Environment/Daemons
Summary: OpenHIP Host Identity Protocol usermode for Linux
Prefix: /usr/local
Provides: openhip
Release: 1
Source: openhip-%{version}.tgz
URL: http://www.openhip.org
Version: %{version}
Buildroot: /tmp/openhiprpm
%description
OpenHIP is a free, open-source implementation of the Host Identity Protocol (HIP). HIP is being developed within the Internet Engineering Task Force (IETF) and the Internet Research Task Force (IRTF) to study and experiment with HIP and related protocols.
HIP is a specific proposal to decouple network identity from network location in the Internet protocol stack. Historically, IP addresses have served both functions. This dual use of IP addresses is becoming problematic, and there have been many research efforts aimed at studying the decoupling of identifier and locator in the network stack. HIP is a specific proposal that uses public/private key pairs as the host identifiers.
%prep
%setup -q
%build
./bootstrap.sh
./configure
make
%install
rm -rf $RPM_BUILD_ROOT
make DESTDIR=$RPM_BUILD_ROOT install
%clean
rm -rf $RPM_BUILD_ROOT
%files
%defattr(-,root,root)
/usr/local/sbin/hip
/usr/local/sbin/hitgen
/usr/local/sbin/hipstatus
%config /usr/local/etc/hip/known_host_identities.xml
%doc README
%doc AUTHORS
%doc LICENSE
%post
#
# only run these commands upon first installation
if [ "$1" = 1 ] ;
then
/usr/local/sbin/hitgen -conf -file /usr/local/etc/hip/hip.conf
/usr/local/sbin/hitgen -noinput -file /usr/local/etc/hip/my_host_identities.xml
mkdir -p /usr/local/var/log /usr/local/var/run
fi;
%changelog
* Mon May 18 2009 Jeff Ahrenholz <siliconja@sourceforge.net> - 0.6
- updated for 0.6 release, fix install using DESTDIR instead of changing prefix
* Wed Jan 10 2007 Jeff Ahrenholz <siliconja@sourceforge.net> - 0.4
- created spec file for OpenHIP 0.4 release
- uses /usr/local/sbin for binaries

826
src/mac/hip_mac.c Normal file
View File

@ -0,0 +1,826 @@
/*
* Host Identity Protocol
* Copyright (C) 2002-05 the Boeing Company
*
* 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 2 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.
*
* Authors: Jeff Ahrenholz, <jeffrey.m.ahrenholz@boeing.com>
* Tom Henderson <thomas.r.henderson@boeing.com>
* Jeff Meegan jeff.r.meegan@boeing.com
*
*
*/
#ifdef __MACOSX__
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/time.h>
#include <ctype.h>
#include <openssl/sha.h>
#include <openssl/dsa.h>
#include <openssl/asn1.h>
#include <openssl/rand.h>
#include <arpa/inet.h> /* inet_addr() */
#ifdef __MACOSX__
#include <netinet/in_systm.h>
#endif
#include <netinet/in.h> /* INADDR_NONE */
#include <netinet/ip.h> /* INADDR_NONE */
#include <sys/types.h>
#include <sys/wait.h> /* wait_pid() */
#include <sys/uio.h> /* iovec */
#include <errno.h>
#include <fcntl.h> /* open() */
#include <netdb.h> /* gethostbyname */
#ifndef __MACOSX__
#include <asm/types.h>
#else
#include <sys/types.h>
#include <net/route.h>
#endif
#include <netinet/ip6.h>
#include <sys/ioctl.h> /* set_link_params() support */
#include <sys/socket.h> /* socket() */
#include <net/if.h>
#include <net/if_dl.h>
#include <ifaddrs.h>
#include <hip/hip_types.h>
#include <hip/hip_proto.h>
#include <hip/hip_globals.h>
#include <hip/hip_funcs.h>
#include <hip/hip_stun.h>
/* Local functions */
/* int read_netlink_response();*/
void readdress_association(int add, struct sockaddr *newaddr, int if_index);
void association_add_address(hip_assoc *hip_a, struct sockaddr *newaddr,
int if_index);
void association_del_address(hip_assoc *hip_a, struct sockaddr *newaddr,
int if_index);
void handle_local_address_change(int add,struct sockaddr *newaddr,int if_index);
#ifdef __MACOSX__
int g_rulebase = 100; /* starting IPFW ruleno */
int g_divertport = 5150; /* divert port */
#endif
/* misnomer because Darwin/OSX doesn't have NETLINK sockets */
int hip_netlink_open()
{
if(s_net) close(s_net);
if ((s_net = socket(PF_ROUTE, SOCK_RAW, PF_UNSPEC)) < 0)
return -1;
/* todo: need to bind()??? */
return 0;
}
#ifndef __MACOSX__
extern int send_udp_esp_tunnel_activation (__u32 spi_out);
#endif
/*
* function select_preferred_address()
*
* Choose one of this machine's IP addresses as preferred.
* - any user preference should take priority, i.e. which interface to use
* - first select an active address having a default gateway
*
*/
int select_preferred_address()
{
int preferred_selected;
sockaddr_list *l;
__u32 ip;
/* Linux version */
/* XXX TODO: dump routing table and choose addr w/default route. */
preferred_selected = FALSE;
/* when a preferred address has not been found yet, choose
* the first that is not a loopback address
*/
if (!preferred_selected) {
for (l = my_addr_head; l; l=l->next) {
if (l->addr.ss_family != AF_INET)
continue;
ip = ((struct sockaddr_in*)&l->addr)->sin_addr.s_addr;
if ((ntohl(ip)==INADDR_LOOPBACK) ||
(ip == 0x01000001L) || ((ip & 0xFFFF) == 0xFEA9))
continue;
l->preferred = TRUE;
log_(NORM, "%s selected as the ",logaddr(SA(&l->addr)));
log_(NORM, "preferred address (2).\n");
break;
}
}
return(0);
}
/*
* function devname_to_index()
*
* Convert device name to numeric index, and also return the MAC address.
* Similar to librtnetlink ll_init_map() and ll_name_to_index(), but
* no map is retained, no caching is performed (meant to be called only once).
*/
/*
* function read_netlink_response()
*
* Called to parse the netlink response without checking for anything
* but errors.
*/
/*
* function add_address_to_list()
*
* Make a sockaddr and add it to a list.
*/
sockaddr_list *add_address_to_list(sockaddr_list **list, struct sockaddr *addr,
int ifi)
{
sockaddr_list *item, *l_p;
/* make a new sockaddr_list element */
item = (sockaddr_list*) malloc(sizeof(sockaddr_list));
if (!item)
return NULL;
memset(item, 0, sizeof(sockaddr_list));
memcpy(&item->addr, addr, SALEN(addr));
item->if_index = ifi;
item->next = NULL;
/* append element to list */
if (*list) {
for(l_p = *list; l_p->next; l_p = l_p->next) /* skip... */;
l_p->next = item;
} else {
*list = item;
}
return(item);
}
/*
* function delete_address_from_list()
*
* Remove a given address from the list, or remove all addresses associated
* with if_index (when len==0).
*/
void delete_address_from_list(sockaddr_list **list, struct sockaddr *addr,
int ifi)
{
sockaddr_list *item, *prev;
int remove;
if (!*list) /* no list */
return;
remove = FALSE;
prev = NULL;
item = *list;
while (item) {
/* remove from list if if_index matches */
if (!addr) {
if (item->if_index == ifi)
remove = TRUE;
/* remove from list if address matches */
} else {
if ((item->addr.ss_family == addr->sa_family) &&
(memcmp(SA2IP(&item->addr), SA2IP(addr),
SAIPLEN(addr))==0)) {
/* address match */
remove = TRUE;
}
}
if (!remove) { /* nothing to delete, advance in list... */
prev = item;
item = item->next;
continue;
}
remove = FALSE;
if (prev) {
prev->next = item->next;
free(item);
item = prev->next;
} else { /* delete first item in list */
*list = item->next;
free(item);
item = *list;
}
}
}
void delete_address_entry_from_list(sockaddr_list **list, sockaddr_list *entry)
{
sockaddr_list *item, *prev;
if (!*list) /* no list */
return;
prev = NULL;
item = *list;
while (item) {
/* pointer match */
if (item == entry) {
if (prev) {
prev->next = item->next;
free(item);
item = prev->next;
} else {
/* for hi_node->addrs, we cannot delete
* the first item in the list! */
return;
}
break;
} else {
prev = item;
item = item->next;
}
}
}
/*
* function is_my_address()
*
* Returns the interface index if supplied address is found in my_addr_head,
* FALSE (0) otherwise. (The interface index is never zero.)
*/
int is_my_address(struct sockaddr *addr)
{
sockaddr_list *l;
for (l = my_addr_head; l; l=l->next) {
if (addr->sa_family != l->addr.ss_family) {
continue;
}
if (memcmp(SA2IP(&l->addr), SA2IP(addr), SAIPLEN(addr))==0) {
/* address match */
return(l->if_index);
}
}
return FALSE;
}
void print_addr_list(sockaddr_list *list)
{
sockaddr_list *l;
log_(NORM, "Address list: [");
for (l = my_addr_head; l; l=l->next) {
log_(NORM, "(%d)%s, ", l->if_index,
logaddr((struct sockaddr*)&l->addr));
}
log_(NORM, "]\n");
}
/*
* function hip_handle_netlink()
*
* Handles received netlink messages. Returns 1 if address change requires
* selection/publishing new preferred address, 0 otherwise.
*/
#define ROUNDUP(a) \
((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
int hip_handle_netlink(char *data, int len)
{
struct rt_msghdr *hd = (struct rt_msghdr *)data;
struct if_msghdr *ifm;
struct ifa_msghdr *ifam;
struct sockaddr *packed; /* For decoding addresses */
struct sockaddr unpacked[4096];
int is_add, retval = 0,i=0,loc=0;
struct sockaddr_storage ss_addr;
struct sockaddr *addr;
sockaddr_list *l;
#ifndef __MACOSX__
NatType nattype;
#endif
addr = (struct sockaddr *) &ss_addr;
switch (hd->rtm_type) {
case RTM_NEWADDR:
case RTM_DELADDR:
ifam = (struct ifa_msghdr *)data;
ifm = (struct if_msghdr *)data;
packed=(struct sockaddr*)
(data+sizeof(struct ifa_msghdr));
memset(addr, 0, sizeof(struct sockaddr_storage));
is_add = (hd->rtm_type ==RTM_NEWADDR);
/* extract list of addresses from message */
for( i = 0; i < RTAX_MAX; i++ ) {
bzero(&unpacked[i],sizeof(unpacked[i]));
if( ifam->ifam_addrs & (1<<i) ) {
memcpy(&(unpacked[i]), packed,
packed->sa_len);
packed=(struct sockaddr*)
(((char*)packed)+ROUNDUP(packed->sa_len));
if(i == RTAX_IFA) {
loc = i;
break;
}
}
}
addr->sa_family = unpacked[loc].sa_family;
memcpy( SA2IP(addr), SA2IP(&unpacked[loc]),
SALEN(&unpacked[loc]));
log_(NORM, "Address %s: (%d)%s \n", (is_add) ? "added" :
"deleted", ifm->ifm_index, logaddr(addr));
#ifndef __MACOSX__
/* NAT detection */
if (OPT.stun && is_add) {
log_(NORMT, "STUN: NAT detection with server ");
printIPv4Addr (&STUN_server_addr);
log_(NORM, "\n");
nattype = stunNatType( &STUN_server_addr,FALSE, NULL, NULL, 0, NULL) ;
if (nattype == StunTypeOpen || nattype == StunTypeFirewall) {
is_behind_nat = FALSE ;
log_(NORM, "STUN: No NAT detected.\n");
} else {
is_behind_nat = TRUE ;
log_(NORM, "STUN: NAT detected, UDP encapsulation activated.\n");
}
}
#endif
handle_local_address_change(is_add, addr,
ifm->ifm_index);
/* update our global address list */
if (is_add) {
l = add_address_to_list(&my_addr_head, addr,
ifm->ifm_index);
l->status = ACTIVE;
/* Need to select_preferred_address() and
* publish_my_hits() here, but the address
* was just added and we may get no route to
* host errors, so handle later */
retval = 1;
} else {
delete_address_from_list(&my_addr_head, addr,
ifm->ifm_index);
}
case RTM_IFINFO:
/* TODO: no ADDLINK/DELLINK netlink messages, so we need
to parse IFINFO messages to discover link changes.
ifm = (struct if_msghdr *)data;
if(!(ifm->ifm_flags & IFF_UP)) {
delete_address_from_list(&my_addr_head, NULL,
ifm->ifm_index);
}
*/
break;
}
return retval;
}
/*
* readdress_association()
*
*
* Handle adding/deleting addresses to/from HIP associations, performing
* readdress when needed. (readdress occurs after a delete + add)
*/
void readdress_association(int add, struct sockaddr *newaddr, int if_index)
{
int i;
hip_assoc *hip_a;
if (!VALID_FAM(newaddr))
return;
/* lookup HIP association based on src interface index */
for (i=0; i < max_hip_assoc; i++) {
hip_a = &hip_assoc_table[i];
if (hip_a->hi->addrs.if_index != if_index)
continue;
if (add) {
association_add_address(hip_a, newaddr, if_index);
} else {
association_del_address(hip_a, newaddr, if_index);
}
}
}
/* An address has been added to this interface, so add it
* to the list in hip_a->hi->addrs.
* If the preferred address was deleted, make this the new
* preferred address and perform readdressing procedures. */
void association_add_address(hip_assoc *hip_a, struct sockaddr *newaddr,
int if_index)
{
sockaddr_list *l;
struct sockaddr *oldaddr;
#ifndef __MACOSX__
int err=0;
#endif
/*
* If preferred address is deleted, do readdress and replace it
*/
if (hip_a->hi->addrs.status == DELETED) {
oldaddr = HIPA_SRC(hip_a);
if (!memcmp(oldaddr, newaddr, SALEN(newaddr))) {
/* address is same, 'undelete' */
make_address_active(&hip_a->hi->addrs);
return;
}
/* perform readdress */
rebuild_sa(hip_a, newaddr, 0, FALSE, FALSE, is_behind_nat);
rebuild_sa(hip_a, newaddr, 0, TRUE, FALSE, is_behind_nat);
sadb_readdress(oldaddr, newaddr, hip_a, hip_a->spi_in);
/* replace the old preferred address */
memcpy(&hip_a->hi->addrs.addr, newaddr,
SALEN(newaddr));
make_address_active(&hip_a->hi->addrs);
if (!hip_a->rekey) {
hip_a->rekey = malloc(sizeof(struct rekey_info));
memset(hip_a->rekey, 0, sizeof(struct rekey_info));
hip_a->rekey->update_id = ++hip_a->hi->update_id;
hip_a->rekey->acked = FALSE;
}
/* // hip_a->use_udp updated after rekeying is completely finished //
if (OPT.stun) {
hip_a->use_udp = is_behind_nat ;
}
*/
if (OPT.stun) {
hip_a->next_use_udp = is_behind_nat;
}
if (is_behind_nat) { /* && hip_a->peer_dst_port==0) { */
hip_a->peer_dst_port = HIP_UDP_PORT;
hip_a->peer_esp_dst_port = HIP_ESP_UDP_PORT;
}
/* .next and .if_index should be already set */
/* inform peer of new preferred address */
if (hip_send_update(hip_a, newaddr, NULL, is_behind_nat) < 0)
log_(WARN, "Problem sending UPDATE(REA) for %s!\n",
logaddr(newaddr));
#ifndef __MACOSX__
if (hip_a->use_udp) { /* (HIP_ESP_OVER_UDP) */
/* not necessary. it is just meant to update the port for incoming packets sent before
rekeying is completely finished */
err = send_udp_esp_tunnel_activation (hip_a->spi_out);
if (err<0) {
printf("Activation of UDP-ESP channel failed.\n");
} else {
printf("Activation of UDP-ESP channel for spi:0x%x done.\n",
hip_a->spi_out);
}
}
#endif
/*
* Add the new address to the end of the list (or unmark deleted status)
*/
} else {
for (l = &hip_a->hi->addrs; l->next; l=l->next){
if (newaddr->sa_family != l->addr.ss_family)
continue;
if (!memcmp(SA2IP(&l->addr), SA2IP(newaddr),
SAIPLEN(&l->addr))) {
/* entry already exists */
make_address_active(l);
return;
}
}
/* add new entry to the end of the list */
l->next = malloc(sizeof(sockaddr_list));
memset(l->next, 0, sizeof(sockaddr_list));
l->next->next = NULL;
memcpy(&l->next->addr, newaddr, SALEN(newaddr));
l->next->if_index = if_index;
}
}
/* An address has been deleted from this interface,
* so mark its status as DELETED.
*/
void association_del_address(hip_assoc *hip_a, struct sockaddr *newaddr,
int if_index)
{
sockaddr_list *l;
for (l = &hip_a->hi->addrs; l; l=l->next) {
if (newaddr->sa_family != l->addr.ss_family)
continue;
if (!memcmp(SA2IP(&l->addr), SA2IP(newaddr), SAIPLEN(&l->addr)))
break;
}
if (l)
l->status = DELETED;
}
void make_address_active(sockaddr_list *item)
{
if (!item)
return;
item->status = ACTIVE;
gettimeofday(&item->creation_time, NULL);
}
/*
* function set_link_params()
*
* Uses ioctl(), not rtnetlink, just like ip command.
* equivalent of:
* "/sbin/ip link set hip0 mtu 1400"
* "/sbin/ip link set hip0 up"
* (see iproute2 source file ip/iplink.c)
*/
int set_link_params(char *dev, int mtu)
{
int err=0;
int fd;
struct ifreq ifr;
__u32 flags, mask;
if ((fd = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
log_(WARN, "set_link_up(): socket error: %s\n",
strerror(errno));
return(-1);
}
/* set link MTU */
memset(&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_name, dev, IFNAMSIZ);
ifr.ifr_mtu = mtu;
err = ioctl(fd, SIOCSIFMTU, &ifr);
if (err) {
log_(WARN, "set_link_params(): SIOCSIFMTU error: %s\n",
strerror(errno));
/* non-fatal error */
}
/* set link to UP */
memset(&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_name, dev, IFNAMSIZ);
err = ioctl(fd, SIOCGIFFLAGS, &ifr); /* get flags */
if (err) {
log_(WARN, "set_link_up(): SIOCGIFFLAGS error: %s\n",
strerror(errno));
close(fd);
return(-1);
}
flags = mask = IFF_UP;
if ((ifr.ifr_flags^flags)&mask) { /* modify flags */
ifr.ifr_flags &= ~mask;
ifr.ifr_flags |= mask&flags;
err = ioctl(fd, SIOCSIFFLAGS, &ifr);
if (err)
log_(WARN, "set_link_up(): SIOCSIFFLAGS error: %s\n",
strerror(errno));
}
close(fd);
return(err);
}
/*
OSX/Darwin version of devname_to_index - uses getifaddrs() instead
of netlink.
jeffm
*/
int devname_to_index( char *dev, __u64 *mac)
{
struct ifaddrs *ifap0, *ifap=0;
struct sockaddr_dl *sdl;
int retVal = -1;
char buf[BUFSIZ];
memset(buf, 0, sizeof(buf));
if (getifaddrs(&ifap0)) {
freeifaddrs(ifap);
return(-1);
}
for (ifap = ifap0; ifap; ifap=ifap->ifa_next) {
if (ifap->ifa_addr == NULL)
continue;
if (strcmp(ifap->ifa_name,dev) != 0)
continue;
if(ifap->ifa_addr->sa_family == AF_LINK) {
sdl = (struct sockaddr_dl*)ifap->ifa_addr;
memcpy(mac,sdl->sdl_data+sdl->sdl_nlen,6);
retVal = sdl->sdl_index;
}
}
freeifaddrs(ifap);
return retVal;
}
/*
retrieve set of addresses via getifaddrs() and add to hip address list
*/
int get_my_addresses()
{
struct ifaddrs *ifap0=0, *ifap=0;
int ix;
char buf[BUFSIZ];
memset(buf, 0, sizeof(buf));
if (getifaddrs(&ifap0)) {
freeifaddrs(ifap);
return 0;
}
for (ifap = ifap0; ifap; ifap=ifap->ifa_next) {
if (ifap->ifa_addr == NULL)
continue;
if (ifap->ifa_addr->sa_family == AF_INET ||
ifap->ifa_addr->sa_family == AF_INET6) {
ix = if_nametoindex(ifap->ifa_name);
add_address_to_list(&my_addr_head,ifap->ifa_addr,ix);
log_(NORM, "(%d)%s ",ix,logaddr(ifap->ifa_addr));
}
}
freeifaddrs(ifap);
return 1;
}
/*
adds a new address to an interface - used to set address on tun device
Note: This will most likely not support IPv6 as written :)
*/
int add_address_to_iface(struct sockaddr *addr, int plen, int if_index)
{
int sock=0;
int stat = 0;
struct ifreq ifr;
if((sock=socket(PF_INET,SOCK_DGRAM,0))<0)
{
return (-1);
}
memset(&ifr,0,sizeof( struct ifreq ) );
/* convert name to interface index */
if_indextoname(if_index,ifr.ifr_name);
log_(WARN,"Adding new addres to interface %s\n",ifr.ifr_name);
memcpy(&ifr.ifr_addr, addr, sizeof(struct sockaddr_in));
/*if(ioctl(sock,SIOCSIFADDR, &ifr )!=0)*/
stat = ioctl(sock,SIOCSIFADDR, &ifr);
log_(WARN,"status = %d\n",stat);
if(ioctl(sock,SIOCSIFADDR, &ifr )!=0)
{
close(sock);
return (-1);
}
close(sock);
return(0);
}
char *ip2dot(__u32 ip)
{
static char buff[32];
int i;
char *p= &buff[0];
sprintf(p, "%u", ((char *)&ip)[0] & 0xff);
p += strlen(p);
for (i=1; i<4 ; ++i) {
sprintf(p, ".%u", ((char *)&ip)[i] & 0xff);
p += strlen(p);
}
*p = 0;
return (char *) &buff[0];
}
/*
return next rule ID
*/
int next_divert_rule()
{
return g_rulebase++;
}
/*
Add a IPFW divert rule. Used during
*/
void add_divert_rule(int ruleno, int proto, char *src)
{
char buf[1024];
sprintf(buf,"/sbin/ipfw add %d divert %d %d from %s to any in",
ruleno,g_divertport,proto,src);
system(buf);
log_(NORM,"Adding IPFW rule %d for dest %s\n",ruleno,src);
}
/*
delete an IPFW divert rule. Used during readdress
as well as connection teardown
*/
void del_divert_rule(int ruleno)
{
char buf[255];
sprintf(buf,"/sbin/ipfw del %d",ruleno);
system(buf);
log_(NORM,"Deleting IPFW rule %d\n",ruleno);
}
/*
* handle_local_address_change()
*
* Handle adding/deleting addresses to/from HIP associations, performing
* readdress when needed. (readdress occurs after a preferred has been deleted)
*/
void handle_local_address_change(int add, struct sockaddr *newaddr,int if_index)
{
int i;
hip_assoc *hip_a;
if (!VALID_FAM(newaddr))
return;
/* lookup HIP association based on src interface index */
for (i=0; i < max_hip_assoc; i++) {
hip_a = &hip_assoc_table[i];
if (hip_a->hi->addrs.if_index != if_index)
continue;
if (add) {
association_add_address(hip_a, newaddr, if_index);
} else {
association_del_address(hip_a, newaddr, if_index);
}
}
}
/*
* update the address of a peer in the peer_hi_head list
*/
int update_peer_list_address(const hip_hit peer_hit, struct sockaddr *old_addr, struct sockaddr *new_addr)
{
sockaddr_list *l;
hi_node *peer_hi = find_host_identity(peer_hi_head, peer_hit);
if (!peer_hi)
return(-1);
if (!new_addr)
return(-1);
l = &peer_hi->addrs;
/* remove old address, if any specified */
if (old_addr) /* or should we just flag deleted? */
delete_address_from_list(&l, old_addr, 0);
/* add the new address */
l = add_address_to_list(&l, new_addr, 0);
return ( l ? 0 : -1 );
}
#endif

1369
src/protocol/hip_addr.c Normal file

File diff suppressed because it is too large Load Diff

459
src/protocol/hip_cache.c Normal file
View File

@ -0,0 +1,459 @@
/*
* Host Identity Protocol
* Copyright (C) 2002-06 the Boeing Company
*
* 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 2 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.
*
* hip_cache.c
*
* Authors: Jeff Ahrenholz, <jeffrey.m.ahrenholz@boeing.com>
* Tom Henderson <thomas.r.henderson@boeing.com>
*
* R1 Management Cache
* Stores precomputed R1s and their cookie solutions.
* Also stores DH contexts.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#ifdef __WIN32__
#include <winsock2.h>
#include <ws2tcpip.h>
#else
#include <unistd.h>
#include <sys/time.h>
#ifdef __MACOSX__
#include <netinet/in_systm.h>
#endif
#include <netinet/in.h>
#endif
#include <openssl/sha.h>
#include <openssl/dsa.h>
#include <openssl/asn1.h>
#include <openssl/rand.h>
#ifndef __CYGWIN__
#ifndef __WIN32__
#include <netinet/ip6.h>
#endif
#endif
#include <sys/types.h>
#include <errno.h>
#include <hip/hip_types.h>
#include <hip/hip_globals.h>
#include <hip/hip_funcs.h>
static __u32 current_rand; /* current random num. used to get cookie index */
static __u32 previous_rand; /* previous random num. used to get cookie index */
static int current_index=0; /* index of R1 cache slot replaced next */
/************************************
* R1 Cache functions *
***********************************/
/* The R1 cache is a hash table of precomputed R1s. Each Host Identity bears
* it's own R1 cache so that packets can be pre-signed for that HI.
* Periodically one of the entries is expired and re-created in a round-robin
* fashion. Each R1 cache entry contains its own cookie puzzle, and the
* previously-used cookie puzzle. Entries also point to the DH entry of the
* context used in the R1 packet.
*/
/*
* ini_all_R1_caches
*
* in/out: none
*
* Initialize all of my Host Identities
* (Call init_R1_cache for every HI in my_hi_head.)
*/
void init_all_R1_caches()
{
hi_node *h;
/* assume random number generator already seeded by init_crypto() */
/* pick a new random number for cookie mapping function */
RAND_bytes((unsigned char *)&current_rand, 4);
previous_rand = 0;
/* initialize the cache for every one of our HIs */
for (h=my_hi_head; h; h=h->next)
init_R1_cache(h);
}
/*
* init_R1_cache()
*
* in: hi = the HI containing the R1 cache to initialize
*
* Populate the R1 cache with pre-computed R1s.
*/
void init_R1_cache(hi_node *hi)
{
int i, len;
r1_cache_entry *entry;
if (!hi) return;
log_(NORM, "Initializing R1 cache entries for identity %s (%d slots)."
"\n", hi->name, R1_CACHE_SIZE);
/* increase generation counter for this new set of R1s */
if (hi->r1_gen_count > 0)
hi->r1_gen_count++;
len = calculate_r1_length(hi);
for (i=0; i<R1_CACHE_SIZE; i++) {
entry = &hi->r1_cache[i];
entry->current_puzzle = generate_cookie();
entry->dh_entry = get_dh_entry(HCNF.dh_group, FALSE);
entry->dh_entry->ref_count++;
entry->packet = (__u8 *) malloc(len);
if (entry->packet == NULL)
log_(NORM, "Malloc error! creating R1 packet.\n");
entry->len = hip_generate_R1(entry->packet, hi,
entry->current_puzzle,
entry->dh_entry);
entry->previous_puzzle = NULL;
gettimeofday(&entry->creation_time, NULL);
}
}
/*
* generate_cookie()
*
* in: none
* out: the new cookie. mmm, cookies.
*
* Generates a new random cookie puzzle.
*/
hipcookie *generate_cookie()
{
hipcookie *cookie;
cookie = (hipcookie*) malloc(sizeof(hipcookie));
memset(cookie, 0, sizeof(hipcookie));
/* generate random 64-bit I */
RAND_bytes((unsigned char*)&cookie->i, 8);
/* K and lifetime are set from configuration */
cookie->k = (__u8)HCNF.cookie_difficulty;
cookie->lifetime = (__u8)HCNF.cookie_lifetime;
cookie->opaque = 0;
return cookie;
}
/*
* replace_next_R1()
*
* in/out: none
*
* Called every few minutes to expire and replace one R1.
* Also picks a new random number for the cookie index mapping function.
*/
void replace_next_R1()
{
hi_node *h;
r1_cache_entry *entry;
/*log_(NORMT, "Expiring the R1 in cache slot %d.\n", current_index);*/
/* every so often pick a new random number
* (twice per cycle through current_index) */
if ((current_index % (R1_CACHE_SIZE/2)) == 2) {
previous_rand = current_rand;
RAND_bytes((unsigned char*)&current_rand, 4);
}
/* for all local Host Identities */
for (h=my_hi_head; h; h=h->next) {
entry = &h->r1_cache[current_index];
/* new R1 entry may use a different cookie, DH entry */
entry->dh_entry->ref_count--;
if (entry->previous_puzzle)
free(entry->previous_puzzle);
entry->previous_puzzle = entry->current_puzzle;
/* generate a new R1 entry */
entry->current_puzzle = generate_cookie();
entry->dh_entry = get_dh_entry(HCNF.dh_group, FALSE);
entry->dh_entry->ref_count++;
free(entry->packet);
entry->packet = (__u8 *) malloc(calculate_r1_length(h));
if (entry->packet == NULL)
log_(NORMT, "Malloc error! Trying to create R1 packet.\n");
entry->len = hip_generate_R1(entry->packet, h, entry->current_puzzle,
entry->dh_entry);
gettimeofday(&entry->creation_time, NULL);
/* index is about to roll over, so all R1s have been replaced
* at this point, we can increase the R1 generation count
*/
if ((current_index + 1 >= R1_CACHE_SIZE) && (h->r1_gen_count > 0))
h->r1_gen_count++;
} /* end for */
current_index++;
if (current_index >= R1_CACHE_SIZE)
current_index = 0;
}
/*
* compute_cookie_index()
*
* in: src = source address of I1 or I2 packet
* hiti = initiator's HIT
* current = TRUE means use current random number, FALSE means
* use the previous random number
*
* Hash function to return an index to an R1 entry given src, HIT.
* This mapping function must be considerably cheaper than computing SHA-1
*/
int compute_R1_cache_index(hip_hit *hiti, __u8 current)
{
__u32 r, *p;
int i;
if (current)
r = current_rand;
else
r = previous_rand;
/* r = random + HIT
* this is similar to checksumming, without using the overflow bit
*/
p = (__u32*) hiti;
for (i=0; i<HIT_SIZE; i+= 4) {
r += *p++;
}
r %= R1_CACHE_SIZE;
return (r);
}
int calculate_r1_length(hi_node *hi)
{
int i, len, num_hip_transforms=0, num_esp_transforms=0, hi_len=0;
/* count transforms */
for (i=0; i<SUITE_ID_MAX; i++) {
if (HCNF.hip_transforms[i] > 0)
num_hip_transforms++;
if (HCNF.esp_transforms[i] > 0)
num_esp_transforms++;
}
hi_len = build_tlv_hostid_len(hi, HCNF.send_hi_name);
if (HCNF.n_reg_types == 0)
len = sizeof(hiphdr) + sizeof(tlv_esp_info) +
sizeof(tlv_r1_counter) + sizeof(tlv_puzzle) +
sizeof(tlv_diffie_hellman) + dhprime_len[HCNF.dh_group] +
eight_byte_align(sizeof(tlv_hip_transform)-2 +
2*num_hip_transforms) +
eight_byte_align(sizeof(tlv_esp_transform)-2 +
2*num_esp_transforms) +
eight_byte_align(hi_len) +
eight_byte_align(sizeof(tlv_cert) + MAX_CERT_LEN - 1) +
/* if opaque is used, add its length here */
eight_byte_align(sizeof(tlv_hip_sig) + MAX_SIG_SIZE - 1);
else
len = sizeof(hiphdr) + sizeof(tlv_esp_info) +
sizeof(tlv_r1_counter) + sizeof(tlv_puzzle) +
sizeof(tlv_diffie_hellman) + dhprime_len[HCNF.dh_group] +
eight_byte_align(sizeof(tlv_hip_transform)-2 +
2*num_hip_transforms) +
eight_byte_align(sizeof(tlv_esp_transform)-2 +
2*num_esp_transforms) +
eight_byte_align(sizeof(tlv_reg_info)-1 + HCNF.n_reg_types) +
eight_byte_align(hi_len) +
eight_byte_align(sizeof(tlv_cert) + MAX_CERT_LEN - 1) +
/* if opaque is used, add its length here */
eight_byte_align(sizeof(tlv_hip_sig) + MAX_SIG_SIZE - 1);
return(eight_byte_align(len));
}
/************************************
* Diffie-Hellman Cache functions *
***********************************/
/* Stores Diffie-Hellman contexts used in precomputed R1s (R1 cache) and those
* made when generating the I2. The only pre-generated DH entry will be for
* the default group ID, so that R1s can be quickly precomputed. DH entries
* become stale after HCNF.dh_lifetime (15 minutes) at which point they are
* no longer used for new R1 packets. Entries are deleted once stale and
* no longer referenced.
*
*/
/*
* init_dh_cache()
*
* Initialize the Diffie-Hellman cache
* Add a single DH entry for the default configured group ID.
*/
void init_dh_cache()
{
/* only called with empty cache */
if (dh_cache)
return;
dh_cache = new_dh_cache_entry(HCNF.dh_group);
}
/*
* new_dh_cache_entry()
*
* in: group_id = the DH group for the new entry
*
* out: returns a new malloc'd DH cache entry
*
* Build a new DH cache entry for the requested DH group.
*/
dh_cache_entry *new_dh_cache_entry(__u8 group_id)
{
int err;
dh_cache_entry *entry;
entry = (dh_cache_entry*) malloc(sizeof(dh_cache_entry));
entry->next = NULL;
entry->group_id = group_id;
entry->is_current = TRUE;
entry->ref_count = 0;
entry->dh = DH_new();
entry->dh->g = BN_new();
entry->dh->p = BN_new();
/* Put prime corresponding to group_id into dh->p */
BN_bin2bn(dhprime[group_id],
dhprime_len[group_id], entry->dh->p);
/* Put generator corresponding to group_id into dh->g */
BN_set_word(entry->dh->g, dhgen[group_id]);
/* By not setting dh->priv_key, allow crypto lib to pick at random */
if ((err = DH_generate_key(entry->dh)) != 1) {
log_(ERR, "DH key generation failed.\n");
log_(NORMT, "DH key generation failed.\n");
exit(1);
}
gettimeofday(&entry->creation_time, NULL);
return(entry);
}
/*
* get_dh_entry()
*
* in: group_id = the DH group desired
* new = TRUE if a new entry is needed (i.e. rekeying),
* FALSE if a cached entry is OK.
*
* out: returns an existing, non-stale entry, or creates a new one
*
*/
dh_cache_entry *get_dh_entry(__u8 group_id, int new)
{
dh_cache_entry *entry, *last=NULL;
for (entry = dh_cache; entry != NULL; entry=entry->next) {
if (!new &&
(entry->group_id == group_id) &&
(entry->is_current==TRUE))
return entry;
/* may want to check if entry is stale here */
last = entry;
}
/* no entry exists for specified group_id or a new entry was requested,
* so generate a new one */
entry = new_dh_cache_entry(group_id);
/* add it to the cache */
last->next = entry;
return entry;
}
/*
* unuse_dh_entry()
*
* in: dh = pointer to DH context contained in the entry
* out: None.
*
* Given a DH context, find the corresponding cache entry and decrement
* its usage count.
*/
void unuse_dh_entry(DH *dh)
{
dh_cache_entry *entry;
for (entry = dh_cache; entry != NULL; entry=entry->next) {
if (entry->dh == dh) {
if (entry->ref_count > 0)
entry->ref_count--;
return;
}
}
}
/*
* expire_old_dh_entries()
*
* in/out: none
*
* Called periodically to expire stale entries and delete unused entries
* from the cache.
*/
void expire_old_dh_entries()
{
dh_cache_entry *entry, *last=NULL, *old;
struct timeval now;
gettimeofday(&now, NULL);
entry = dh_cache;
while (entry != NULL)
{
if (TDIFF(now, entry->creation_time) > (int)HCNF.dh_lifetime) {
/* mark entry as stale */
entry->is_current = FALSE;
/* delete unused cache entry */
if (entry->ref_count == 0) {
old = entry;
/* replace default entry */
if (old->group_id == HCNF.dh_group) {
entry =
new_dh_cache_entry(old->group_id);
entry->next = old->next;
if (last)
last->next = entry;
else
dh_cache = entry;
/* remove non-default entries */
} else {
if (last)
last->next = old->next;
else
dh_cache = old->next;
}
/*log_(NORMT, "Freeing old DH entry.\n");*/
DH_free(old->dh);
free(old);
}
}
last = entry;
entry=entry->next;
}
}

801
src/protocol/hip_dht.c Normal file
View File

@ -0,0 +1,801 @@
/*
* Host Identity Protocol
* Copyright (C) 2005-06 the Boeing Company
*
* 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 2 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.
*
* hip_dht.c
*
* Author: Jeff Ahrenholz, <jeffrey.m.ahrenholz@boeing.com>
*
* DHT interface for publishing IP addresses using the HIT as the key.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef __WIN32__
#include <winsock2.h>
#include <ws2tcpip.h>
#include <win32/types.h>
#include <io.h>
#include <process.h>
#else
#include <unistd.h>
#include <sys/time.h>
#ifdef __MACOSX__
#include <netinet/in_systm.h>
#endif
#include <netinet/in.h> /* INADDR_NONE */
#include <netinet/ip.h> /* INADDR_NONE */
#include <pthread.h> /* pthreads support */
#endif
#include <openssl/evp.h>
#ifndef __CYGWIN__
#ifndef __WIN32__
#include <netinet/ip6.h>
#endif
#endif
#include <sys/types.h>
#include <errno.h>
#include <fcntl.h> /* open() */
#include <libxml/tree.h> /* XML support */
#ifndef __MACOSX__
#include <libxml/xmlwriter.h>
#endif
#include <hip/hip_version.h> /* HIP_VERSION */
#include <hip/hip_types.h>
#include <hip/hip_globals.h>
#include <hip/hip_funcs.h>
/* constants */
#define XMLRPC_MODE_GET 0x0001
#define XMLRPC_MODE_PUT 0x0002
#define XMLRPC_MODE_RETRY_OFF 0x0010
#define XMLRPC_MODE_RETRY_ON 0x0020
#define XMLRPC_APP_HIT "hip-hit" /* HIT lookup service */
#define XMLRPC_APP_ADDR "hip-addr" /* addr lookup service */
extern __u32 get_preferred_addr();
/* public functions */
int hip_dht_lookup_hit(struct sockaddr *lsi, hip_hit *hit, int retry);
int hip_dht_lookup_address(hip_hit *hit, struct sockaddr *addr, int retry);
int hip_dht_publish_addr(hip_hit *hit, struct sockaddr *addr, int retry);
int hip_dht_publish_hit(struct sockaddr *lsi, hip_hit *hit, int retry);
int hip_dht_select_server(struct sockaddr *addr);
/* local functions */
#ifdef __WIN32__
void add_addresses_from_dht_thread(void *void_hi);
void publish_my_hits_thread(sockaddr_list *l);
#else
void *add_addresses_from_dht_thread(void *void_hi);
#endif
int hip_xmlrpc_getput(int mode, char *app, struct sockaddr *server,
char *key, int key_len, char *value, int value_len);
int hip_xmlrpc_parse_response(int mode, char *xmldata, int len,
char *value, int value_len);
xmlNodePtr xml_new_param(xmlNodePtr node_parent, char *type, char *value);
int build_http_post_header(char *buff, int content_len, struct sockaddr *addr);
/*
* function hip_dht_lookup_hit()
*
* in: lsi = LSI used for lookup
* out: hit = pointer to store HIT
* Returns 0 on success, -1 on error.
*
* Given an LSI, lookup associated HIT using a DHT server.
*/
int hip_dht_lookup_hit(struct sockaddr *lsi, hip_hit *hit, int retry)
{
int mode;
struct sockaddr_storage ss_server;
struct sockaddr *server = (struct sockaddr*)&ss_server;
if (hip_dht_select_server(server) < 0)
return(-1);
/* log_(NORM, "hip_dht_lookup_hit(%s, hitp=%p, retry=%d)\n",
logaddr(lsi),hit,retry); // */
/*
* For the Bamboo DHT (OpenDHT), this is tied
* to an XML RPC "GET" call
*/
mode = XMLRPC_MODE_GET;
mode |= (retry) ? XMLRPC_MODE_RETRY_ON : XMLRPC_MODE_RETRY_OFF;
return(hip_xmlrpc_getput(mode, XMLRPC_APP_HIT, server,
(char *)lsi, SALEN(lsi), (char *)hit, HIT_SIZE));
}
/*
* function hip_dht_lookup_address()
*
* in: hit = pointer to HIT for use with the lookup
* out: addr = pointer to sockaddr_storage
* Returns 0 on success, -1 on error.
*
* Given a HIT, lookup an address using a DHT server.
*/
int hip_dht_lookup_address(hip_hit *hit, struct sockaddr *addr, int retry)
{
int mode, err;
struct sockaddr_storage ss_server;
struct sockaddr *server = (struct sockaddr*)&ss_server;
if (hip_dht_select_server(server) < 0)
return(-1);
/*
* For the Bamboo DHT (OpenDHT), this is tied
* to an XML RPC "GET" call
*/
mode = XMLRPC_MODE_GET;
mode |= (retry) ? XMLRPC_MODE_RETRY_ON : XMLRPC_MODE_RETRY_OFF;
err = hip_xmlrpc_getput(mode, XMLRPC_APP_ADDR, server,
(char *)hit, HIT_SIZE, (char *)addr, SALEN(addr));
if (!VALID_FAM(addr)) /* check that an address was returned */
return(-1);
return(err);
}
/*
* function hip_dht_publish_hit()
*
* in: lsi = LSI to use as the DHT key
* hit = HIT to use for the DHT value
* out: Returns 0 on success, -1 on error.
*
* Store this LSI and HIT on the DHT server.
*/
int hip_dht_publish_hit(struct sockaddr *lsi, hip_hit *hit, int retry)
{
int mode;
struct sockaddr_storage ss_server;
struct sockaddr *server = (struct sockaddr*)&ss_server;
if (hip_dht_select_server(server) < 0)
return(-1);
/* log_(NORM, "hip_dht_publish_hit(%s, hitp=%p, retry=%d)\n",
logaddr(lsi),hit,retry); // */
/*
* For the Bamboo DHT (OpenDHT), this is tied
* to an XML RPC "PUT" call
*/
mode = XMLRPC_MODE_PUT;
mode |= (retry) ? XMLRPC_MODE_RETRY_ON : XMLRPC_MODE_RETRY_OFF;
return(hip_xmlrpc_getput(mode, XMLRPC_APP_HIT, server,
(char *)lsi, SALEN(lsi), (char *)hit, HIT_SIZE));
}
/*
* function hip_dht_publish_addr()
*
* in: hit = HIT to use as the DHT key
* addr = address to use for the DHT value
* out: Returns 0 on success, -1 on error.
*
* Store this HIT and address on the DHT server.
*/
int hip_dht_publish_addr(hip_hit *hit, struct sockaddr *addr, int retry)
{
int mode;
struct sockaddr_storage ss_server;
struct sockaddr *server = (struct sockaddr*)&ss_server;
if (hip_dht_select_server(server) < 0)
return(-1);
/*
* For the Bamboo DHT (OpenDHT), this is tied
* to an XML RPC "PUT" call
*/
mode = XMLRPC_MODE_PUT;
mode |= (retry) ? XMLRPC_MODE_RETRY_ON : XMLRPC_MODE_RETRY_OFF;
return(hip_xmlrpc_getput(mode, XMLRPC_APP_ADDR, server,
(char *)hit, HIT_SIZE, (char *)addr, SALEN(addr)));
}
/*
* function hip_dht_select_server()
*
* out: addr = pointer to store address of the server
* Returns 0 on success, -1 on error.
*
* Select the address of the DHT server to use.
*/
int hip_dht_select_server(struct sockaddr *addr)
{
/*
* we leave room for more complex server selection schemes here
*
* for now, a single server+port is specified via the conf file
*
*/
if (VALID_FAM(&HCNF.dht_server)) {
memcpy(addr, &HCNF.dht_server, SALEN(&HCNF.dht_server));
return(0);
}
return(-1);
}
/*******************************************************************************
* Below are HIP helper functions that are DHT releated
*
******************************************************************************/
/*
* function add_addresses_from_dht()
*
* in: hi = contains HIT for lookup, hi->addrs for storing result
* retry = if TRUE, will fork and allow hip_dht_lookup_address()
* to retry multiple times
* Given a Host Identity, perform a DHT lookup using its HIT and store any
* resulting address in the hi_node.
*/
int add_addresses_from_dht(hi_node *hi, int retry)
{
int err;
struct sockaddr_storage ss_addr;
struct sockaddr *addr = (struct sockaddr*) &ss_addr;
#ifndef __WIN32__
pthread_attr_t attr;
pthread_t thr;
#endif
/* When retry is turned on, a separate thread will be forked that
* will perform the DHT lookup(s), retry a certain number of times,
* and exit */
if (retry) {
#ifdef __WIN32__
_beginthread(add_addresses_from_dht_thread, 0, (void *)hi);
#else
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
pthread_create(&thr, &attr, add_addresses_from_dht_thread, hi);
#endif
return(0);
}
/* If there is no HIT configured, first use DHT
* to find it using the LSI */
if (hits_equal(hi->hit, zero_hit)) {
log_(NORM, "HIT not present for %s, performing lookup.\n",
logaddr(SA(&hi->lsi)));
if ((err = hip_dht_lookup_hit( SA(&hi->lsi),
&hi->hit, retry)) < 0) {
/* no HIT from LSI, so we cannot do address lookup */
log_(WARN, "Unable to find HIT for %s in the DHT.\n",
logaddr(SA(&hi->lsi)));
return(err);
/*} else {
log_(NORM, "DHT err=%d HIT=", err);
print_hex(hi->hit, HIT_SIZE);
log_(NORM, "\n");*/
}
}
/* lookup current IP address using HIT */
addr->sa_family = AF_INET;
if ((err = hip_dht_lookup_address(&hi->hit, addr, retry)) < 0) {
if (retry)
exit(0);
else
return(err);
/*} else {
log_(NORM, "DHT err=%d ADDR=%s\n", err, logaddr(addr));
*/
}
/* assume since we are here, there are no addresses in
* the XML file, nor in DNS, and the addrlist is empty */
pthread_mutex_lock(&hi->addrs_mutex);
memset(&hi->addrs, 0, sizeof(sockaddr_list));
memcpy(&hi->addrs.addr, addr, SALEN(addr));
pthread_mutex_unlock(&hi->addrs_mutex);
/* in the future, may want to retrieve multiple
* addresses, and use add_address_to_list()
*/
return(0);
}
#ifdef __WIN32__
void add_addresses_from_dht_thread(void *void_hi)
#else
void *add_addresses_from_dht_thread(void *void_hi)
#endif
{
hi_node *hi = (hi_node*)void_hi;
int err;
struct sockaddr_storage ss_addr;
struct sockaddr *addr = (struct sockaddr*) &ss_addr;
/* If there is no HIT configured, first use DHT
* to find it using the LSI*/
if (hits_equal(hi->hit, zero_hit)) {
log_(NORM, "HIT not present for %s, performing lookup.\n",
logaddr(SA(&hi->lsi)));
if ((err = hip_dht_lookup_hit( SA(&hi->lsi),
&hi->hit, TRUE)) < 0) {
/* no HIT from LSI, so we cannot do address lookup */
log_(WARN, "Unable to find HIT for %s in the DHT.\n",
logaddr(SA(&hi->lsi)));
goto add_addresses_from_dht_thread_exit;
/*} else {
log_(NORM, "DHT err=%d HIT=", err);
print_hex(hi->hit, HIT_SIZE);
log_(NORM, "\n");*/
}
}
/* lookup current IP address using HIT */
addr->sa_family = AF_INET;
if ((err = hip_dht_lookup_address(&hi->hit, addr, TRUE)) < 0) {
goto add_addresses_from_dht_thread_exit;
/*} else {
log_(NORM, "DHT err=%d ADDR=%s\n", err, logaddr(addr));
*/
}
/* assume since we are here, there are no addresses in
* the XML file, nor in DNS, and the addrlist is empty */
pthread_mutex_lock(&hi->addrs_mutex);
memset(&hi->addrs, 0, sizeof(sockaddr_list));
memcpy(&hi->addrs.addr, addr, SALEN(addr));
pthread_mutex_unlock(&hi->addrs_mutex);
/* in the future, may want to retrieve multiple
* addresses, and use add_address_to_list()
*/
add_addresses_from_dht_thread_exit:
#ifdef __WIN32__
return;
#else
return(NULL);
#endif
}
/*
* function publish_my_hits()
*
* Publish (HIT, IP) and (LSI, HIT) combinations to a DHT,
* to support both type of lookups.
*/
void publish_my_hits()
{
sockaddr_list *l;
#ifndef __WIN32__
hi_node *hi;
#endif
#ifdef SMA_CRAWLER
struct sockaddr_storage ss_server;
struct sockaddr *server = (struct sockaddr*)&ss_server;
if (hip_dht_select_server(server) < 0)
return;
#endif
/* for now, only publish our preferred address */
for (l = my_addr_head; l; l=l->next) {
if (IS_LSI(&l->addr)) /* skip any LSIs */
continue;
if (l->preferred)
break;
}
if (!l)
return;
/* parent process returns */
#ifdef __WIN32__
_beginthread(publish_my_hits_thread, 0, l);
return;
}
void publish_my_hits_thread(sockaddr_list *l) {
hi_node *hi;
#else
if (fork() != 0)
return;
#endif
/* send a publish request for each configured HIT */
for (hi = my_hi_head; hi; hi=hi->next) {
/* since retry is on, if there is an error returned
* we will give up trying */
if (hip_dht_publish_addr(&hi->hit,
(struct sockaddr*) &l->addr, TRUE) < 0)
break;
if (hip_dht_publish_hit((struct sockaddr*)&hi->lsi,
&hi->hit, TRUE) < 0)
break;
}
#ifndef __WIN32__
_exit(0);
#endif
}
/*******************************************************************************
* Below are functions specific to different DHT implementations.
*
*
******************************************************************************/
/*
* function hip_xmlrpc_getput()
*
* in: mode = determines get or put, app, retry on/off
* If retry is off only one attempt should be made,
* on means the connect() should keep retrying
* server = server address and port
* hit = HIT used as key for get or put
* addr = address to publish for PUTs, storage for GETs
*
* Since XML RPC GET and PUT for the Bamboo DHT are so similar, both are
* handled in the same function below.
*/
int hip_xmlrpc_getput(int mode, char *app, struct sockaddr *server,
char *key, int key_len, char *value, int value_len)
{
xmlDocPtr doc = NULL;
xmlNodePtr root_node = NULL, node;
int len=0, s, retval=0;
char buff[2048];
unsigned char key64[30], val64[30], tmp[32], *xmlbuff=NULL;
fd_set read_fdset;
struct timeval timeout;
char *p;
unsigned int retry_attempts = 0;
struct sockaddr_in src_addr;
int retry = ((mode & 0x00F0) == XMLRPC_MODE_RETRY_ON);
/*
* create a new XML document
*/
doc = xmlNewDoc(BAD_CAST "1.0");
root_node = xmlNewNode(NULL, BAD_CAST "methodCall");
xmlDocSetRootElement(doc, root_node);
node = xmlNewChild(root_node, NULL, BAD_CAST "methodName",
BAD_CAST(((mode & 0x000F) == XMLRPC_MODE_PUT) ? "put": "get"));
node = xmlNewChild(root_node, NULL, BAD_CAST "params", NULL);
memset(tmp, 0, sizeof(tmp));
memcpy(tmp, key, key_len);
EVP_EncodeBlock(key64, tmp, key_len);
xml_new_param(node, "base64", (char *)key64); /* key */
/* log_(NORM, "Doing %s using key(%d)=",
((mode & 0x000F)==XMLRPC_MODE_PUT) ? "PUT":"GET", key_len);
print_hex(key, key_len);
log_(NORM, " [%s]\n", base64); // */
if ((mode & 0x000F) == XMLRPC_MODE_PUT) {
memcpy(tmp, value, value_len);
EVP_EncodeBlock(val64, tmp, value_len);
xml_new_param(node, "base64", (char *)val64); /* value */
xml_new_param(node, "int", "604800"); /* lifetime */
/*log_(NORM, "value(%d)=", value_len);
print_hex(value, value_len);
log_(NORM, " [%s]\n", base64); // */
} else if ((mode & 0x000F) == XMLRPC_MODE_GET) {
/* additional GET parameters */
xml_new_param(node, "int", "10"); /* maxvals */
xml_new_param(node, "base64", ""); /* placemark */
memset(value, 0, value_len);
}
xml_new_param(node, "string", app); /* app */
xmlDocDumpFormatMemory(doc, &xmlbuff, &len, 0);
/*
* Build an HTTP POST and transmit to server
*/
memset(buff, 0, sizeof(buff));
build_http_post_header(buff, len, server); /* len is XML length above */
memcpy(&buff[strlen(buff)], xmlbuff, len);
xmlFree(xmlbuff);
len = strlen(buff) + 1;
connect_retry:
/* Connect and send the XML RPC */
if ((s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
log_(WARN, "DHT connect - socket error: %s\n", strerror(errno));
retval = -1;
goto putget_exit;
}
/* Use the preferred address as source */
memset(&src_addr, 0, sizeof(src_addr));
src_addr.sin_family = AF_INET;
src_addr.sin_addr.s_addr = get_preferred_addr();
if (!src_addr.sin_addr.s_addr) {
log_(NORM, "No preferred address, deferring DHT!\n");
return(-1);
}
log_(NORM, "Using source address of %s for DHT lookup.\n",
logaddr(SA(&src_addr)));
fflush(stdout);
if (bind(s, SA(&src_addr), SALEN(&src_addr)) < 0) {
log_(WARN, "DHT connect - bind error: %s\n", strerror(errno));
}
#ifdef __UMH__
if (g_state != 0)
return -1;
#endif
if (retry && (retry_attempts > 0)) {
/* quit after a certain number of retries */
if (retry_attempts >= HCNF.max_retries) {
retval = -2;
goto putget_exit;
}
/* wait packet_timeout seconds before retrying */
hip_sleep(HCNF.packet_timeout);
}
retry_attempts++;
if (connect(s, server, SALEN(server)) < 0) {
log_(WARN, "DHT server connect error: %s\n", strerror(errno));
#ifdef __WIN32__
closesocket(s);
#else
close(s);
#endif
#ifdef __WIN32__
errno = WSAGetLastError();
if (retry && ((errno == WSAETIMEDOUT) ||
(errno == WSAENETUNREACH)))
goto connect_retry;
#else
if (retry && ((errno == ETIMEDOUT) || (errno == EHOSTUNREACH)))
goto connect_retry;
#endif
retval = -3;
goto putget_exit;
}
if (send(s, buff, len, 0) != len) {
log_(WARN, "DHT sent incorrect number of bytes\n");
retval = -4;
goto putget_exit;
}
xmlFreeDoc(doc);
doc = NULL;
/*
* Receive XML RPC response from server
*/
FD_ZERO(&read_fdset);
FD_SET((unsigned int)s, &read_fdset);
/* use longer timeout when retry==TRUE, because we have own thread */
if (retry) {
timeout.tv_sec = 3;
timeout.tv_usec = 0;
} else {
timeout.tv_sec = 0;
timeout.tv_usec = 300000; /* 300ms */
}
if (select(s+1, &read_fdset, NULL, NULL, &timeout) < 0) {
log_(WARN, "DHT select error: %s\n", strerror(errno));
retval = -5;
goto putget_exit;
} else if (FD_ISSET(s, &read_fdset)) {
if ((len = recv(s, buff, sizeof(buff)-1, 0)) <= 0) {
log_(WARN, "DHT error receiving from server: %s\n",
strerror(errno));
retval = -6;
goto putget_exit;
}
if (strncmp(buff, "HTTP", 4) != 0)
return(-7);
if ((p = strstr(buff, "Content-Length: ")) == NULL)
return(-8);
else /* advance ptr to Content-Length */
p += 16;
sscanf(p, "%d", &len);
p = strchr(p, '\n') + 3; /* advance to end of line */
retval = hip_xmlrpc_parse_response(mode, p, len,
value, value_len);
} else {
/* select timeout */
if (retry) /* XXX testme: retry select instead? */
goto connect_retry;
retval = -9;
}
putget_exit:
#ifdef __WIN32__
closesocket(s);
#else
close(s);
#endif
if (doc != NULL) xmlFreeDoc(doc);
return(retval);
}
/*
* function xml_new_param()
*
* insert a value embedded in XML in the format
* <param><value><type>value</type></value></param>
*/
xmlNodePtr xml_new_param(xmlNodePtr node_parent, char *type, char *value)
{
xmlNodePtr node_param, node_value;
node_param = xmlNewChild(node_parent, NULL, BAD_CAST "param", NULL);
node_value = xmlNewChild(node_param, NULL, BAD_CAST "value", NULL);
return(xmlNewChild(node_value, NULL, BAD_CAST type, BAD_CAST value));
}
/*
* function build_http_post_header()
*/
int build_http_post_header(char *buff, int content_len, struct sockaddr *addr)
{
unsigned short port = 0;
char addrstr[INET6_ADDRSTRLEN];
addr_to_str(addr, (__u8*)addrstr, INET6_ADDRSTRLEN);
if (AF_INET == addr->sa_family)
port = ntohs(((struct sockaddr_in*)addr)->sin_port);
else if (AF_INET6 == addr->sa_family)
port = ntohs(((struct sockaddr_in6*)addr)->sin6_port);
sprintf(buff, "POST /RPC2 HTTP/1.0\r\nUser-Agent: %s %s\r\nHost: %s:%d\r\nContent-Type: text/xml\r\nContent-length: %d\r\n\r\n",
HIP_NAME, HIP_VERSION, addrstr, port, content_len);
return(strlen(buff));
}
/*
* function hip_xmlrpc_parse_response()
*
* in: mode = is this an XML RPC GET/PUT? store response in hit/addr?
* xmldata = pointer to XML character data
* len = length of data
*
* out: For GETs, the address or HIT is returned in addr or hit,
* and 0 is returned for success.
* For PUTs, the XML RPC return code is returned,
* which is 0 for success, or 1 or 2. -1 is returned on error.
*/
int hip_xmlrpc_parse_response(int mode, char *xmldata, int len,
char *value, int value_len)
{
xmlDocPtr doc = NULL;
xmlNodePtr node, node_val;
int retval=-10;
xmlChar *data;
/*
printf("Got the response (content-length=%d):\n", len);
printf(xmldata);
printf("\n");
// */
if ((doc = xmlParseMemory(xmldata, len)) == NULL)
goto parse_response_exit;
node = xmlDocGetRootElement(doc); /* <methodResponse> */
if (node->children) node = node->children; /* <params> */
node = node->children;
if (!node) /* <param> */
goto parse_response_exit;
node_val = NULL;
if (!strcmp((char *)node->name, "param") && node->children &&
!strcmp((char *)node->children->name, "value"))
node_val = node->children->children;
if (!node_val)
goto parse_response_exit;
if ((mode & 0x000F) == XMLRPC_MODE_PUT) {/* retrieve status code only */
data = xmlNodeGetContent(node_val);
/* status code is first int that we encounter */
if (strcmp((char *)node_val->name, "int")==0) {
sscanf((const char *)data, "%d", &retval);
xmlFree(data);
goto parse_response_exit;
}
} else { /* retrieve address or HIT */
/* <?xml version="1.0" encoding="ISO-8859-1"?>
* <methodResponse>
* <params><param><value><array><data>
* <value><array><data>
* <value><base64>AgAAAMCoAQAAAAAAA==</base64></value>
* <value><base64>AgAAAMCoAgcAAAAAA==</base64></value>
* </data></array></value>
* <value><base64></base64></value>
* </data></array></value></param></params>
* </methodResponse>
*/
if (!strcmp((char *)node_val->name, "array") &&
node_val->children &&
!strcmp((char *)node_val->children->name, "data"))
node = node_val->children->children;
if (!strcmp((char *)node->name, "value") && node->children &&
!strcmp((char *)node->children->name, "array"))
node = node->children->children; /* <data> */
/* step through array of responses */
for (node = node->children; node; node = node->next) {
node_val = node->children; /* <value><base64> */
if ((!node_val) ||
(strcmp((char *)node_val->name, "base64")))
continue;
data = xmlNodeGetContent(node_val);
/* protect against unusually large values */
if (strlen((char *)data) >
((unsigned)(((value_len+2)/3) *4)+1)) {
xmlFree(data);
continue;
}
/* decode base64 into value pointer */
EVP_DecodeBlock((unsigned char *)value,
data, strlen((char *)data));
retval = 0;
xmlFree(data);
/* the last value encountered will be returned */
} /* end for */
/* placemark and other tags are ignored */
}
parse_response_exit:
if (doc != NULL) xmlFreeDoc(doc);
return(retval);
}
/* Testing code -- compile with:
* gcc -g -Wall -o hip_dht hip_dht.c hip_globals.o hip_util.o -lcrypto -L/usr/lib -lxml2 -lz -liconv -lm -I/usr/include/libxml2 -DTEST_XMLRPC
*/
#ifdef TEST_XMLRPC
sockaddr_list *add_address_to_list(sockaddr_list **list, struct sockaddr *addr,
int ifi) { return NULL; }
void delete_address_from_list(sockaddr_list **list, struct sockaddr *addr,
int ifi)
{ return; }
void unuse_dh_entry(DH *dh) { return; }
int flush_hip_associations() { return 0;}
int g_state;
int main(int argc, char **argv)
{
int err, publish;
hip_hit hit;
struct sockaddr_storage addr;
struct sockaddr_in *addr4 = (struct sockaddr_in*)&addr;
memset(&addr, 0, sizeof(addr));
addr4->sin_family = AF_INET;
addr4->sin_addr.s_addr = inet_addr("192.168.1.2");
hex_to_bin("7BE901B3AF2679C8C580619535641713", hit, HIT_SIZE);
printf("Doing XML RPC put 1...\n");
err = hip_dht_publish(&hit, (struct sockaddr*)&addr);
printf("return value = %d\n", err);
addr4->sin_addr.s_addr = inet_addr("192.168.2.7");
printf("Doing XML RPC put 2...\n");
err = hip_dht_publish(&hit, (struct sockaddr*)&addr);
printf("return value = %d\n", err);
addr4->sin_addr.s_addr = 0;
memset(&addr, 0, sizeof(addr));
addr4->sin_family = AF_INET;
printf("addr is at: %p\n", &addr);
printf("Doing XML RPC get...\n");
err = hip_dht_lookup_address(&hit, (struct sockaddr*)&addr);
printf("return value = %d\n", err);
printf("Address = %s\n", logaddr((struct sockaddr*)&addr));
return(0);
}
#endif /* TEST_XMLRPC */

367
src/protocol/hip_globals.c Normal file
View File

@ -0,0 +1,367 @@
/*
* Host Identity Protocol
* Copyright (C) 2002-06 the Boeing Company
*
* 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 2 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.
*
* hip_globals.c
*
* Authors: Jeff Ahrenholz, <jeffrey.m.ahrenholz@boeing.com>
* Tom Henderson, <thomas.r.henderson@boeing.com>
*
* Global data for the HIP daemon.
*
*/
#include <openssl/dsa.h> /* DSA support */
#include <openssl/dh.h> /* Diffie-Hellman contexts */
#include <hip/hip_types.h>
#include <hip/hip_proto.h>
#include <hip/hip_stun.h>
/* globals */
/* Registration global variables */
long int num_entries = 0;
int min_life = 0;
int max_life = 0;
int reg_type = 0;
int add_reg_info = FALSE;
int add_reg_request = FALSE;
int add_reg_response = FALSE;
int add_reg_failed = FALSE;
int resp_lifetime = 0;
int resp_reg_type = 0;
int fail_type = 0;
int fail_reg_type = 0;
int repeat_reg = FALSE;
int repeat_type = 0;
int need_to_send_update2 = FALSE;
/* Relaying global variables (used only in rvs mode) */
from fr;
int no_R1 = FALSE;
/* Relaying global variables (used in normal mode) */
via fr2;
/* table of active connections or exchanges */
hip_assoc hip_assoc_table[MAX_CONNECTIONS];
int max_hip_assoc=0; /* last entry added to the table */
/* Mobile router client table */
hip_mr_client hip_mr_client_table[MAX_MR_CLIENTS];
int max_hip_mr_clients = 0;
int external_if_index = -1;
int new_external_address = 0;
hip_hit mobile_router_hit;
hip_mutex_t hip_mr_client_mutex;
/* table of active registrations */
hip_reg hip_reg_table[MAX_REGISTRATIONS];
long int num_hip_reg = 0;
hi_node *my_hi_head = NULL;
sockaddr_list *my_addr_head = NULL;
hi_node *peer_hi_head = NULL;
dh_cache_entry *dh_cache = NULL;
const hip_hit zero_hit = {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
int pfk_seqno=0; /* sequence number for sending PF_KEY messages */
int s_hip = 0;
int s_hip_udp = 0;
int s_pfk = 0;
int s6_hip = 0; /* PFKEY and RAW socket handles */
#undef s_net
int s_net = 0; /* netlink socket */
int s_stat = 0; /* status socket */
int is_behind_nat = 0;
StunAddress4 STUN_server_addr;
/* Global options */
struct hip_opt OPT;
/* Global configuration data */
struct hip_conf HCNF;
/*
* Diffie-Hellman primes
*/
/* 384-bit Group */
unsigned char dhprime_384[] = {
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC9,0x0F,0xDA,0xA2,
0x21,0x68,0xC2,0x34,0xC4,0xC6,0x62,0x8B,0x80,0xDC,0x1C,0xD1,
0x29,0x02,0x4E,0x08,0x8A,0x67,0xCC,0x74,0x02,0x0B,0xBE,0xA6,
0x3B,0x13,0xB2,0x02,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
};
/* RFC 2412 Oakley Group 1 768-bit, 96 bytes */
unsigned char dhprime_oakley_1[] = {
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC9,0x0F,0xDA,0xA2,
0x21,0x68,0xC2,0x34,0xC4,0xC6,0x62,0x8B,0x80,0xDC,0x1C,0xD1,
0x29,0x02,0x4E,0x08,0x8A,0x67,0xCC,0x74,0x02,0x0B,0xBE,0xA6,
0x3B,0x13,0x9B,0x22,0x51,0x4A,0x08,0x79,0x8E,0x34,0x04,0xDD,
0xEF,0x95,0x19,0xB3,0xCD,0x3A,0x43,0x1B,0x30,0x2B,0x0A,0x6D,
0xF2,0x5F,0x14,0x37,0x4F,0xE1,0x35,0x6D,0x6D,0x51,0xC2,0x45,
0xE4,0x85,0xB5,0x76,0x62,0x5E,0x7E,0xC6,0xF4,0x4C,0x42,0xE9,
0xA6,0x3A,0x36,0x20,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
};
/* RFC 3526 MODP 1536-bit = RFC 2412 Oakley Group 5 */
unsigned char dhprime_modp_1536[] = {
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC9,0x0F,0xDA,0xA2,
0x21,0x68,0xC2,0x34,0xC4,0xC6,0x62,0x8B,0x80,0xDC,0x1C,0xD1,
0x29,0x02,0x4E,0x08,0x8A,0x67,0xCC,0x74,0x02,0x0B,0xBE,0xA6,
0x3B,0x13,0x9B,0x22,0x51,0x4A,0x08,0x79,0x8E,0x34,0x04,0xDD,
0xEF,0x95,0x19,0xB3,0xCD,0x3A,0x43,0x1B,0x30,0x2B,0x0A,0x6D,
0xF2,0x5F,0x14,0x37,0x4F,0xE1,0x35,0x6D,0x6D,0x51,0xC2,0x45,
0xE4,0x85,0xB5,0x76,0x62,0x5E,0x7E,0xC6,0xF4,0x4C,0x42,0xE9,
0xA6,0x37,0xED,0x6B,0x0B,0xFF,0x5C,0xB6,0xF4,0x06,0xB7,0xED,
0xEE,0x38,0x6B,0xFB,0x5A,0x89,0x9F,0xA5,0xAE,0x9F,0x24,0x11,
0x7C,0x4B,0x1F,0xE6,0x49,0x28,0x66,0x51,0xEC,0xE4,0x5B,0x3D,
0xC2,0x00,0x7C,0xB8,0xA1,0x63,0xBF,0x05,0x98,0xDA,0x48,0x36,
0x1C,0x55,0xD3,0x9A,0x69,0x16,0x3F,0xA8,0xFD,0x24,0xCF,0x5F,
0x83,0x65,0x5D,0x23,0xDC,0xA3,0xAD,0x96,0x1C,0x62,0xF3,0x56,
0x20,0x85,0x52,0xBB,0x9E,0xD5,0x29,0x07,0x70,0x96,0x96,0x6D,
0x67,0x0C,0x35,0x4E,0x4A,0xBC,0x98,0x04,0xF1,0x74,0x6C,0x08,
0xCA,0x23,0x73,0x27,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
};
/* RFC 3526 MODP 3072-bit, 384 bytes */
unsigned char dhprime_modp_3072[] = {
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC9,0x0F,0xDA,0xA2,
0x21,0x68,0xC2,0x34,0xC4,0xC6,0x62,0x8B,0x80,0xDC,0x1C,0xD1,
0x29,0x02,0x4E,0x08,0x8A,0x67,0xCC,0x74,0x02,0x0B,0xBE,0xA6,
0x3B,0x13,0x9B,0x22,0x51,0x4A,0x08,0x79,0x8E,0x34,0x04,0xDD,
0xEF,0x95,0x19,0xB3,0xCD,0x3A,0x43,0x1B,0x30,0x2B,0x0A,0x6D,
0xF2,0x5F,0x14,0x37,0x4F,0xE1,0x35,0x6D,0x6D,0x51,0xC2,0x45,
0xE4,0x85,0xB5,0x76,0x62,0x5E,0x7E,0xC6,0xF4,0x4C,0x42,0xE9,
0xA6,0x37,0xED,0x6B,0x0B,0xFF,0x5C,0xB6,0xF4,0x06,0xB7,0xED,
0xEE,0x38,0x6B,0xFB,0x5A,0x89,0x9F,0xA5,0xAE,0x9F,0x24,0x11,
0x7C,0x4B,0x1F,0xE6,0x49,0x28,0x66,0x51,0xEC,0xE4,0x5B,0x3D,
0xC2,0x00,0x7C,0xB8,0xA1,0x63,0xBF,0x05,0x98,0xDA,0x48,0x36,
0x1C,0x55,0xD3,0x9A,0x69,0x16,0x3F,0xA8,0xFD,0x24,0xCF,0x5F,
0x83,0x65,0x5D,0x23,0xDC,0xA3,0xAD,0x96,0x1C,0x62,0xF3,0x56,
0x20,0x85,0x52,0xBB,0x9E,0xD5,0x29,0x07,0x70,0x96,0x96,0x6D,
0x67,0x0C,0x35,0x4E,0x4A,0xBC,0x98,0x04,0xF1,0x74,0x6C,0x08,
0xCA,0x18,0x21,0x7C,0x32,0x90,0x5E,0x46,0x2E,0x36,0xCE,0x3B,
0xE3,0x9E,0x77,0x2C,0x18,0x0E,0x86,0x03,0x9B,0x27,0x83,0xA2,
0xEC,0x07,0xA2,0x8F,0xB5,0xC5,0x5D,0xF0,0x6F,0x4C,0x52,0xC9,
0xDE,0x2B,0xCB,0xF6,0x95,0x58,0x17,0x18,0x39,0x95,0x49,0x7C,
0xEA,0x95,0x6A,0xE5,0x15,0xD2,0x26,0x18,0x98,0xFA,0x05,0x10,
0x15,0x72,0x8E,0x5A,0x8A,0xAA,0xC4,0x2D,0xAD,0x33,0x17,0x0D,
0x04,0x50,0x7A,0x33,0xA8,0x55,0x21,0xAB,0xDF,0x1C,0xBA,0x64,
0xEC,0xFB,0x85,0x04,0x58,0xDB,0xEF,0x0A,0x8A,0xEA,0x71,0x57,
0x5D,0x06,0x0C,0x7D,0xB3,0x97,0x0F,0x85,0xA6,0xE1,0xE4,0xC7,
0xAB,0xF5,0xAE,0x8C,0xDB,0x09,0x33,0xD7,0x1E,0x8C,0x94,0xE0,
0x4A,0x25,0x61,0x9D,0xCE,0xE3,0xD2,0x26,0x1A,0xD2,0xEE,0x6B,
0xF1,0x2F,0xFA,0x06,0xD9,0x8A,0x08,0x64,0xD8,0x76,0x02,0x73,
0x3E,0xC8,0x6A,0x64,0x52,0x1F,0x2B,0x18,0x17,0x7B,0x20,0x0C,
0xBB,0xE1,0x17,0x57,0x7A,0x61,0x5D,0x6C,0x77,0x09,0x88,0xC0,
0xBA,0xD9,0x46,0xE2,0x08,0xE2,0x4F,0xA0,0x74,0xE5,0xAB,0x31,
0x43,0xDB,0x5B,0xFC,0xE0,0xFD,0x10,0x8E,0x4B,0x82,0xD1,0x20,
0xA9,0x3A,0xD2,0xCA,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
};
/* RFC 3526 MODP 6144-bit, 768 bytes */
unsigned char dhprime_modp_6144[] = {
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC9,0x0F,0xDA,0xA2,
0x21,0x68,0xC2,0x34,0xC4,0xC6,0x62,0x8B,0x80,0xDC,0x1C,0xD1,
0x29,0x02,0x4E,0x08,0x8A,0x67,0xCC,0x74,0x02,0x0B,0xBE,0xA6,
0x3B,0x13,0x9B,0x22,0x51,0x4A,0x08,0x79,0x8E,0x34,0x04,0xDD,
0xEF,0x95,0x19,0xB3,0xCD,0x3A,0x43,0x1B,0x30,0x2B,0x0A,0x6D,
0xF2,0x5F,0x14,0x37,0x4F,0xE1,0x35,0x6D,0x6D,0x51,0xC2,0x45,
0xE4,0x85,0xB5,0x76,0x62,0x5E,0x7E,0xC6,0xF4,0x4C,0x42,0xE9,
0xA6,0x37,0xED,0x6B,0x0B,0xFF,0x5C,0xB6,0xF4,0x06,0xB7,0xED,
0xEE,0x38,0x6B,0xFB,0x5A,0x89,0x9F,0xA5,0xAE,0x9F,0x24,0x11,
0x7C,0x4B,0x1F,0xE6,0x49,0x28,0x66,0x51,0xEC,0xE4,0x5B,0x3D,
0xC2,0x00,0x7C,0xB8,0xA1,0x63,0xBF,0x05,0x98,0xDA,0x48,0x36,
0x1C,0x55,0xD3,0x9A,0x69,0x16,0x3F,0xA8,0xFD,0x24,0xCF,0x5F,
0x83,0x65,0x5D,0x23,0xDC,0xA3,0xAD,0x96,0x1C,0x62,0xF3,0x56,
0x20,0x85,0x52,0xBB,0x9E,0xD5,0x29,0x07,0x70,0x96,0x96,0x6D,
0x67,0x0C,0x35,0x4E,0x4A,0xBC,0x98,0x04,0xF1,0x74,0x6C,0x08,
0xCA,0x18,0x21,0x7C,0x32,0x90,0x5E,0x46,0x2E,0x36,0xCE,0x3B,
0xE3,0x9E,0x77,0x2C,0x18,0x0E,0x86,0x03,0x9B,0x27,0x83,0xA2,
0xEC,0x07,0xA2,0x8F,0xB5,0xC5,0x5D,0xF0,0x6F,0x4C,0x52,0xC9,
0xDE,0x2B,0xCB,0xF6,0x95,0x58,0x17,0x18,0x39,0x95,0x49,0x7C,
0xEA,0x95,0x6A,0xE5,0x15,0xD2,0x26,0x18,0x98,0xFA,0x05,0x10,
0x15,0x72,0x8E,0x5A,0x8A,0xAA,0xC4,0x2D,0xAD,0x33,0x17,0x0D,
0x04,0x50,0x7A,0x33,0xA8,0x55,0x21,0xAB,0xDF,0x1C,0xBA,0x64,
0xEC,0xFB,0x85,0x04,0x58,0xDB,0xEF,0x0A,0x8A,0xEA,0x71,0x57,
0x5D,0x06,0x0C,0x7D,0xB3,0x97,0x0F,0x85,0xA6,0xE1,0xE4,0xC7,
0xAB,0xF5,0xAE,0x8C,0xDB,0x09,0x33,0xD7,0x1E,0x8C,0x94,0xE0,
0x4A,0x25,0x61,0x9D,0xCE,0xE3,0xD2,0x26,0x1A,0xD2,0xEE,0x6B,
0xF1,0x2F,0xFA,0x06,0xD9,0x8A,0x08,0x64,0xD8,0x76,0x02,0x73,
0x3E,0xC8,0x6A,0x64,0x52,0x1F,0x2B,0x18,0x17,0x7B,0x20,0x0C,
0xBB,0xE1,0x17,0x57,0x7A,0x61,0x5D,0x6C,0x77,0x09,0x88,0xC0,
0xBA,0xD9,0x46,0xE2,0x08,0xE2,0x4F,0xA0,0x74,0xE5,0xAB,0x31,
0x43,0xDB,0x5B,0xFC,0xE0,0xFD,0x10,0x8E,0x4B,0x82,0xD1,0x20,
0xA9,0x21,0x08,0x01,0x1A,0x72,0x3C,0x12,0xA7,0x87,0xE6,0xD7,
0x88,0x71,0x9A,0x10,0xBD,0xBA,0x5B,0x26,0x99,0xC3,0x27,0x18,
0x6A,0xF4,0xE2,0x3C,0x1A,0x94,0x68,0x34,0xB6,0x15,0x0B,0xDA,
0x25,0x83,0xE9,0xCA,0x2A,0xD4,0x4C,0xE8,0xDB,0xBB,0xC2,0xDB,
0x04,0xDE,0x8E,0xF9,0x2E,0x8E,0xFC,0x14,0x1F,0xBE,0xCA,0xA6,
0x28,0x7C,0x59,0x47,0x4E,0x6B,0xC0,0x5D,0x99,0xB2,0x96,0x4F,
0xA0,0x90,0xC3,0xA2,0x23,0x3B,0xA1,0x86,0x51,0x5B,0xE7,0xED,
0x1F,0x61,0x29,0x70,0xCE,0xE2,0xD7,0xAF,0xB8,0x1B,0xDD,0x76,
0x21,0x70,0x48,0x1C,0xD0,0x06,0x91,0x27,0xD5,0xB0,0x5A,0xA9,
0x93,0xB4,0xEA,0x98,0x8D,0x8F,0xDD,0xC1,0x86,0xFF,0xB7,0xDC,
0x90,0xA6,0xC0,0x8F,0x4D,0xF4,0x35,0xC9,0x34,0x02,0x84,0x92,
0x36,0xC3,0xFA,0xB4,0xD2,0x7C,0x70,0x26,0xC1,0xD4,0xDC,0xB2,
0x60,0x26,0x46,0xDE,0xC9,0x75,0x1E,0x76,0x3D,0xBA,0x37,0xBD,
0xF8,0xFF,0x94,0x06,0xAD,0x9E,0x53,0x0E,0xE5,0xDB,0x38,0x2F,
0x41,0x30,0x01,0xAE,0xB0,0x6A,0x53,0xED,0x90,0x27,0xD8,0x31,
0x17,0x97,0x27,0xB0,0x86,0x5A,0x89,0x18,0xDA,0x3E,0xDB,0xEB,
0xCF,0x9B,0x14,0xED,0x44,0xCE,0x6C,0xBA,0xCE,0xD4,0xBB,0x1B,
0xDB,0x7F,0x14,0x47,0xE6,0xCC,0x25,0x4B,0x33,0x20,0x51,0x51,
0x2B,0xD7,0xAF,0x42,0x6F,0xB8,0xF4,0x01,0x37,0x8C,0xD2,0xBF,
0x59,0x83,0xCA,0x01,0xC6,0x4B,0x92,0xEC,0xF0,0x32,0xEA,0x15,
0xD1,0x72,0x1D,0x03,0xF4,0x82,0xD7,0xCE,0x6E,0x74,0xFE,0xF6,
0xD5,0x5E,0x70,0x2F,0x46,0x98,0x0C,0x82,0xB5,0xA8,0x40,0x31,
0x90,0x0B,0x1C,0x9E,0x59,0xE7,0xC9,0x7F,0xBE,0xC7,0xE8,0xF3,
0x23,0xA9,0x7A,0x7E,0x36,0xCC,0x88,0xBE,0x0F,0x1D,0x45,0xB7,
0xFF,0x58,0x5A,0xC5,0x4B,0xD4,0x07,0xB2,0x2B,0x41,0x54,0xAA,
0xCC,0x8F,0x6D,0x7E,0xBF,0x48,0xE1,0xD8,0x14,0xCC,0x5E,0xD2,
0x0F,0x80,0x37,0xE0,0xA7,0x97,0x15,0xEE,0xF2,0x9B,0xE3,0x28,
0x06,0xA1,0xD5,0x8B,0xB7,0xC5,0xDA,0x76,0xF5,0x50,0xAA,0x3D,
0x8A,0x1F,0xBF,0xF0,0xEB,0x19,0xCC,0xB1,0xA3,0x13,0xD5,0x5C,
0xDA,0x56,0xC9,0xEC,0x2E,0xF2,0x96,0x32,0x38,0x7F,0xE8,0xD7,
0x6E,0x3C,0x04,0x68,0x04,0x3E,0x8F,0x66,0x3F,0x48,0x60,0xEE,
0x12,0xBF,0x2D,0x5B,0x0B,0x74,0x74,0xD6,0xE6,0x94,0xF9,0x1E,
0x6D,0xCC,0x40,0x24,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
};
/* RFC 3526 MODP 8192-bit, 1024 bytes */
unsigned char dhprime_modp_8192[] = {
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC9,0x0F,0xDA,0xA2,
0x21,0x68,0xC2,0x34,0xC4,0xC6,0x62,0x8B,0x80,0xDC,0x1C,0xD1,
0x29,0x02,0x4E,0x08,0x8A,0x67,0xCC,0x74,0x02,0x0B,0xBE,0xA6,
0x3B,0x13,0x9B,0x22,0x51,0x4A,0x08,0x79,0x8E,0x34,0x04,0xDD,
0xEF,0x95,0x19,0xB3,0xCD,0x3A,0x43,0x1B,0x30,0x2B,0x0A,0x6D,
0xF2,0x5F,0x14,0x37,0x4F,0xE1,0x35,0x6D,0x6D,0x51,0xC2,0x45,
0xE4,0x85,0xB5,0x76,0x62,0x5E,0x7E,0xC6,0xF4,0x4C,0x42,0xE9,
0xA6,0x37,0xED,0x6B,0x0B,0xFF,0x5C,0xB6,0xF4,0x06,0xB7,0xED,
0xEE,0x38,0x6B,0xFB,0x5A,0x89,0x9F,0xA5,0xAE,0x9F,0x24,0x11,
0x7C,0x4B,0x1F,0xE6,0x49,0x28,0x66,0x51,0xEC,0xE4,0x5B,0x3D,
0xC2,0x00,0x7C,0xB8,0xA1,0x63,0xBF,0x05,0x98,0xDA,0x48,0x36,
0x1C,0x55,0xD3,0x9A,0x69,0x16,0x3F,0xA8,0xFD,0x24,0xCF,0x5F,
0x83,0x65,0x5D,0x23,0xDC,0xA3,0xAD,0x96,0x1C,0x62,0xF3,0x56,
0x20,0x85,0x52,0xBB,0x9E,0xD5,0x29,0x07,0x70,0x96,0x96,0x6D,
0x67,0x0C,0x35,0x4E,0x4A,0xBC,0x98,0x04,0xF1,0x74,0x6C,0x08,
0xCA,0x18,0x21,0x7C,0x32,0x90,0x5E,0x46,0x2E,0x36,0xCE,0x3B,
0xE3,0x9E,0x77,0x2C,0x18,0x0E,0x86,0x03,0x9B,0x27,0x83,0xA2,
0xEC,0x07,0xA2,0x8F,0xB5,0xC5,0x5D,0xF0,0x6F,0x4C,0x52,0xC9,
0xDE,0x2B,0xCB,0xF6,0x95,0x58,0x17,0x18,0x39,0x95,0x49,0x7C,
0xEA,0x95,0x6A,0xE5,0x15,0xD2,0x26,0x18,0x98,0xFA,0x05,0x10,
0x15,0x72,0x8E,0x5A,0x8A,0xAA,0xC4,0x2D,0xAD,0x33,0x17,0x0D,
0x04,0x50,0x7A,0x33,0xA8,0x55,0x21,0xAB,0xDF,0x1C,0xBA,0x64,
0xEC,0xFB,0x85,0x04,0x58,0xDB,0xEF,0x0A,0x8A,0xEA,0x71,0x57,
0x5D,0x06,0x0C,0x7D,0xB3,0x97,0x0F,0x85,0xA6,0xE1,0xE4,0xC7,
0xAB,0xF5,0xAE,0x8C,0xDB,0x09,0x33,0xD7,0x1E,0x8C,0x94,0xE0,
0x4A,0x25,0x61,0x9D,0xCE,0xE3,0xD2,0x26,0x1A,0xD2,0xEE,0x6B,
0xF1,0x2F,0xFA,0x06,0xD9,0x8A,0x08,0x64,0xD8,0x76,0x02,0x73,
0x3E,0xC8,0x6A,0x64,0x52,0x1F,0x2B,0x18,0x17,0x7B,0x20,0x0C,
0xBB,0xE1,0x17,0x57,0x7A,0x61,0x5D,0x6C,0x77,0x09,0x88,0xC0,
0xBA,0xD9,0x46,0xE2,0x08,0xE2,0x4F,0xA0,0x74,0xE5,0xAB,0x31,
0x43,0xDB,0x5B,0xFC,0xE0,0xFD,0x10,0x8E,0x4B,0x82,0xD1,0x20,
0xA9,0x21,0x08,0x01,0x1A,0x72,0x3C,0x12,0xA7,0x87,0xE6,0xD7,
0x88,0x71,0x9A,0x10,0xBD,0xBA,0x5B,0x26,0x99,0xC3,0x27,0x18,
0x6A,0xF4,0xE2,0x3C,0x1A,0x94,0x68,0x34,0xB6,0x15,0x0B,0xDA,
0x25,0x83,0xE9,0xCA,0x2A,0xD4,0x4C,0xE8,0xDB,0xBB,0xC2,0xDB,
0x04,0xDE,0x8E,0xF9,0x2E,0x8E,0xFC,0x14,0x1F,0xBE,0xCA,0xA6,
0x28,0x7C,0x59,0x47,0x4E,0x6B,0xC0,0x5D,0x99,0xB2,0x96,0x4F,
0xA0,0x90,0xC3,0xA2,0x23,0x3B,0xA1,0x86,0x51,0x5B,0xE7,0xED,
0x1F,0x61,0x29,0x70,0xCE,0xE2,0xD7,0xAF,0xB8,0x1B,0xDD,0x76,
0x21,0x70,0x48,0x1C,0xD0,0x06,0x91,0x27,0xD5,0xB0,0x5A,0xA9,
0x93,0xB4,0xEA,0x98,0x8D,0x8F,0xDD,0xC1,0x86,0xFF,0xB7,0xDC,
0x90,0xA6,0xC0,0x8F,0x4D,0xF4,0x35,0xC9,0x34,0x02,0x84,0x92,
0x36,0xC3,0xFA,0xB4,0xD2,0x7C,0x70,0x26,0xC1,0xD4,0xDC,0xB2,
0x60,0x26,0x46,0xDE,0xC9,0x75,0x1E,0x76,0x3D,0xBA,0x37,0xBD,
0xF8,0xFF,0x94,0x06,0xAD,0x9E,0x53,0x0E,0xE5,0xDB,0x38,0x2F,
0x41,0x30,0x01,0xAE,0xB0,0x6A,0x53,0xED,0x90,0x27,0xD8,0x31,
0x17,0x97,0x27,0xB0,0x86,0x5A,0x89,0x18,0xDA,0x3E,0xDB,0xEB,
0xCF,0x9B,0x14,0xED,0x44,0xCE,0x6C,0xBA,0xCE,0xD4,0xBB,0x1B,
0xDB,0x7F,0x14,0x47,0xE6,0xCC,0x25,0x4B,0x33,0x20,0x51,0x51,
0x2B,0xD7,0xAF,0x42,0x6F,0xB8,0xF4,0x01,0x37,0x8C,0xD2,0xBF,
0x59,0x83,0xCA,0x01,0xC6,0x4B,0x92,0xEC,0xF0,0x32,0xEA,0x15,
0xD1,0x72,0x1D,0x03,0xF4,0x82,0xD7,0xCE,0x6E,0x74,0xFE,0xF6,
0xD5,0x5E,0x70,0x2F,0x46,0x98,0x0C,0x82,0xB5,0xA8,0x40,0x31,
0x90,0x0B,0x1C,0x9E,0x59,0xE7,0xC9,0x7F,0xBE,0xC7,0xE8,0xF3,
0x23,0xA9,0x7A,0x7E,0x36,0xCC,0x88,0xBE,0x0F,0x1D,0x45,0xB7,
0xFF,0x58,0x5A,0xC5,0x4B,0xD4,0x07,0xB2,0x2B,0x41,0x54,0xAA,
0xCC,0x8F,0x6D,0x7E,0xBF,0x48,0xE1,0xD8,0x14,0xCC,0x5E,0xD2,
0x0F,0x80,0x37,0xE0,0xA7,0x97,0x15,0xEE,0xF2,0x9B,0xE3,0x28,
0x06,0xA1,0xD5,0x8B,0xB7,0xC5,0xDA,0x76,0xF5,0x50,0xAA,0x3D,
0x8A,0x1F,0xBF,0xF0,0xEB,0x19,0xCC,0xB1,0xA3,0x13,0xD5,0x5C,
0xDA,0x56,0xC9,0xEC,0x2E,0xF2,0x96,0x32,0x38,0x7F,0xE8,0xD7,
0x6E,0x3C,0x04,0x68,0x04,0x3E,0x8F,0x66,0x3F,0x48,0x60,0xEE,
0x12,0xBF,0x2D,0x5B,0x0B,0x74,0x74,0xD6,0xE6,0x94,0xF9,0x1E,
0x6D,0xBE,0x11,0x59,0x74,0xA3,0x92,0x6F,0x12,0xFE,0xE5,0xE4,
0x38,0x77,0x7C,0xB6,0xA9,0x32,0xDF,0x8C,0xD8,0xBE,0xC4,0xD0,
0x73,0xB9,0x31,0xBA,0x3B,0xC8,0x32,0xB6,0x8D,0x9D,0xD3,0x00,
0x74,0x1F,0xA7,0xBF,0x8A,0xFC,0x47,0xED,0x25,0x76,0xF6,0x93,
0x6B,0xA4,0x24,0x66,0x3A,0xAB,0x63,0x9C,0x5A,0xE4,0xF5,0x68,
0x34,0x23,0xB4,0x74,0x2B,0xF1,0xC9,0x78,0x23,0x8F,0x16,0xCB,
0xE3,0x9D,0x65,0x2D,0xE3,0xFD,0xB8,0xBE,0xFC,0x84,0x8A,0xD9,
0x22,0x22,0x2E,0x04,0xA4,0x03,0x7C,0x07,0x13,0xEB,0x57,0xA8,
0x1A,0x23,0xF0,0xC7,0x34,0x73,0xFC,0x64,0x6C,0xEA,0x30,0x6B,
0x4B,0xCB,0xC8,0x86,0x2F,0x83,0x85,0xDD,0xFA,0x9D,0x4B,0x7F,
0xA2,0xC0,0x87,0xE8,0x79,0x68,0x33,0x03,0xED,0x5B,0xDD,0x3A,
0x06,0x2B,0x3C,0xF5,0xB3,0xA2,0x78,0xA6,0x6D,0x2A,0x13,0xF8,
0x3F,0x44,0xF8,0x2D,0xDF,0x31,0x0E,0xE0,0x74,0xAB,0x6A,0x36,
0x45,0x97,0xE8,0x99,0xA0,0x25,0x5D,0xC1,0x64,0xF3,0x1C,0xC5,
0x08,0x46,0x85,0x1D,0xF9,0xAB,0x48,0x19,0x5D,0xED,0x7E,0xA1,
0xB1,0xD5,0x10,0xBD,0x7E,0xE7,0x4D,0x73,0xFA,0xF3,0x6B,0xC3,
0x1E,0xCF,0xA2,0x68,0x35,0x90,0x46,0xF4,0xEB,0x87,0x9F,0x92,
0x40,0x09,0x43,0x8B,0x48,0x1C,0x6C,0xD7,0x88,0x9A,0x00,0x2E,
0xD5,0xEE,0x38,0x2B,0xC9,0x19,0x0D,0xA6,0xFC,0x02,0x6E,0x47,
0x95,0x58,0xE4,0x47,0x56,0x77,0xE9,0xAA,0x9E,0x30,0x50,0xE2,
0x76,0x56,0x94,0xDF,0xC8,0x1F,0x56,0xE8,0x80,0xB9,0x6E,0x71,
0x60,0xC9,0x80,0xDD,0x98,0xED,0xD3,0xDF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF
};
/* load DH arrays for easy access */
const unsigned char *dhprime[DH_MAX] = {
0,
dhprime_384,
dhprime_oakley_1,
dhprime_modp_1536,
dhprime_modp_3072,
dhprime_modp_6144,
dhprime_modp_8192,
};
const int dhprime_len[DH_MAX] = {
-1,
sizeof(dhprime_384),
sizeof(dhprime_oakley_1),
sizeof(dhprime_modp_1536),
sizeof(dhprime_modp_3072),
sizeof(dhprime_modp_6144),
sizeof(dhprime_modp_8192),
};
unsigned char dhgen[DH_MAX] = {0,0x02,0x02,0x02,0x02,0x02,0x02};
const unsigned char khi_context_id[16] = {
0xf0, 0xef, 0xf0, 0x2f, 0xbf, 0xf4, 0x3d, 0x0f,
0xe7, 0x93, 0x0c, 0x3c, 0x6e, 0x61, 0x74, 0xea
};

4566
src/protocol/hip_input.c Normal file

File diff suppressed because it is too large Load Diff

1831
src/protocol/hip_ipsec.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,692 @@
/*
* Host Identity Protocol
* Copyright (C) 2002-05 the Boeing Company
*
* 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 2 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.
*
* hip_ipsec_win32.c
*
* Authors: Jeff Ahrenholz, <jeffrey.m.ahrenholz@boeing.com>
*
* Functions for communicating with the kernel IPSec implementation using
* the PF_KEYv2 messaging interface.
*
*/
#include <stdio.h> /* stderr, etc */
#include <stdlib.h> /* rand() */
#include <errno.h> /* strerror(), errno */
#include <string.h> /* memset() */
#include <time.h> /* time() */
#include <ctype.h> /* tolower() */
#ifdef __WIN32__
#include <winsock2.h>
#include <ws2tcpip.h> /* for sockaddrin_6 */
#include <io.h> /* read() */
#else
#include <arpa/inet.h> /* inet_addr() */
#include <sys/socket.h> /* sock(), recvmsg(), etc */
#include <unistd.h> /* write() */
#ifdef __MACOSX__
#include <netinet/in_systm.h>
#endif
#include <netinet/in.h> /* struct sockaddr_in, etc */
#include <netinet/ip.h> /* struct iphdr */
#endif
#include <sys/types.h> /* getpid() support, etc */
#include <openssl/crypto.h> /* OpenSSL's crypto library */
#include <openssl/bn.h> /* Big Numbers */
#include <openssl/dsa.h> /* DSA support */
#include <openssl/dh.h> /* Diffie-Hellman contexts */
#include <openssl/sha.h> /* SHA1 algorithms */
#include <openssl/rand.h> /* RAND_seed() */
#ifdef __MACOSX__
#include <sys/types.h>
#include "../win32/pfkeyv2.h"
#else
#ifdef __UMH__
#include <asm/types.h>
#include "../win32/pfkeyv2.h"
#else
#include "/usr/src/linux/include/linux/pfkeyv2.h" /* PF_KEY_V2 support */
#endif
#endif
#include "hip.h"
#include "hip_globals.h"
#define IPSEC_PFKEYv2_ALIGN (sizeof(uint64_t) / sizeof(uint8_t))
#define PFKEY_ALIGN8(a) (1 + (((a) - 1) | (8 - 1)))
/*
* Local function declarations
*/
int build_sa_ext(char *data, __u32 spi, __u8 state, __u8 auth, __u8 encrypt, __u32 flags);
int build_sa2_ext(char *data, __u32 mode);
int build_nat_port_ext(char *data, int type, __u16 port);
int build_lifetime_ext(char *data, int type, __u32 lifetime);
int build_address_ext(char *data, int type, struct sockaddr *addr);
int build_ident_ext(char *data, int type, struct sockaddr *addr);
int build_hit_ext(char *data, int type, uint16_t val);
int pfkey_send_hip_x1 (int sock, u_int type, u_int satype, u_int mode,
struct sockaddr *src, struct sockaddr *dst,
struct sockaddr *isrc, struct sockaddr *idst,
u_int32_t spi,
u_int32_t regid, u_int wsize, caddr_t key,
u_int e_type, u_int e_keylen, u_int a_type, u_int a_keylen,
u_int flags, u_int32_t l_alloc, u_int32_t l_bytes,
u_int32_t l_addtime, u_int32_t l_usetime, u_int32_t seqno,
u_int8_t l_natt_type, u_int16_t l_natt_sport,
u_int16_t l_natt_dport, struct sockaddr *l_natt_oa,
u_int16_t hitmagic)
{
int err, location=0, len=0;
struct sadb_key *pfkey_key;
struct sadb_msg *pfkey_msg;
char buff[SADB_MSG_SIZE_ADD];
location = 0;
/* message header */
pfkey_msg = (struct sadb_msg*) &buff[0];
pfkey_msg->sadb_msg_version = PF_KEY_V2;
pfkey_msg->sadb_msg_type = type;
pfkey_msg->sadb_msg_errno = 0;
pfkey_msg->sadb_msg_satype = satype;
pfkey_msg->sadb_msg_len = -1; /* Will fill in below */
pfkey_msg->sadb_msg_reserved = 0;
pfkey_msg->sadb_msg_seq = seqno;
pfkey_msg->sadb_msg_pid = 0;
len = sizeof(struct sadb_msg);
location += len;
/* SA extension */
location += build_sa_ext(&buff[location], spi,
SADB_SASTATE_MATURE, (__u8)a_type, (__u8)e_type, 0);
/* SA2 extension (for mode) */
if (mode) {
location += build_sa2_ext(&buff[location], mode);
}
/* NAT source/destination port */
if (l_natt_sport > 0)
location += build_nat_port_ext(&buff[location],
SADB_X_EXT_NAT_T_SPORT, l_natt_sport);
if (l_natt_dport > 0)
location += build_nat_port_ext(&buff[location],
SADB_X_EXT_NAT_T_DPORT, l_natt_dport);
/* lifetime extension */
location += build_lifetime_ext(&buff[location],
SADB_EXT_LIFETIME_HARD, l_addtime);
/* source address extension */
location += build_address_ext(&buff[location], SADB_EXT_ADDRESS_SRC,
src);
/* destination address extension */
location += build_address_ext(&buff[location], SADB_EXT_ADDRESS_DST,
dst);
/* inner source/destination address extensions */
if (isrc && idst) {
location += build_ident_ext(&buff[location],
SADB_EXT_IDENTITY_SRC, isrc);
location += build_ident_ext(&buff[location],
SADB_EXT_IDENTITY_DST, idst);
}
/* authentication key extension */
pfkey_key = (struct sadb_key*) &buff[location];
memset(pfkey_key, 0, sizeof(struct sadb_key));
location += sizeof(struct sadb_key); /* 8 bytes */
/*
* With 20 byte auth key, need 8 + 20 + 4 (pad) to
* end up on an 8 byte boundary
*/
pfkey_key->sadb_key_len = eight_byte_align(sizeof(struct sadb_key) +
a_keylen) / IPSEC_PFKEYv2_ALIGN;
pfkey_key->sadb_key_exttype = SADB_EXT_KEY_AUTH;
pfkey_key->sadb_key_bits = a_keylen * 8; /* 160 bits */
pfkey_key->sadb_key_reserved = 0;
/* key[enc_key|auth_key] */
memcpy(&buff[location], &key[e_keylen], a_keylen);
location += a_keylen;
memset(&buff[location], 0, 4); /* padding to 24 bytes */
location += 4;
/* encryption key extension */
pfkey_key = (struct sadb_key*) &buff[location];
memset(pfkey_key, 0, sizeof(struct sadb_key));
location += sizeof(struct sadb_key);
pfkey_key->sadb_key_len = eight_byte_align(sizeof(struct sadb_key) +
e_keylen) / IPSEC_PFKEYv2_ALIGN;
pfkey_key->sadb_key_exttype = SADB_EXT_KEY_ENCRYPT;
pfkey_key->sadb_key_reserved = 0;
pfkey_key->sadb_key_bits = e_keylen*8;
/* key[enc_key|auth_key] */
memcpy(&buff[location], &key[0], e_keylen);
location += e_keylen;
/* insert ext hdr for hip_hit */
location += build_hit_ext(&buff[location], SADB_EXT_HIT, hitmagic);
/*
implementations that don't support the hit ext hdr SHOULD
ignore it.
*/
/* complete the header */
len = location;
pfkey_msg->sadb_msg_len = len / IPSEC_PFKEYv2_ALIGN;
/* send the SADB_ADD message to the kernel */
#ifdef __WIN32__
err = send(sock, (char *)pfkey_msg, len, 0);
#else
err = write(sock, (char *)pfkey_msg, len);
#endif
if (err < 1) {
fprintf(stderr, "sadb_add: pfkey write() error: %s.\n",
strerror(errno));
}
return(err);
}
int pfkey_send_rea (int sock, u_int type, u_int satype,
struct sockaddr *src, struct sockaddr *dst, u_int32_t spi,
u_int e_type, u_int a_type, u_int flags, u_int32_t seqno)
{
struct sadb_msg *pfkey_msg;
int len, err=0, location;
char buff[512];
location = 0;
memset(buff, 0, sizeof(buff));
/* message header */
pfkey_msg = (struct sadb_msg*)&buff[0];
pfkey_msg->sadb_msg_version = PF_KEY_V2;
pfkey_msg->sadb_msg_type = type;
pfkey_msg->sadb_msg_errno = 0;
pfkey_msg->sadb_msg_satype = satype;
pfkey_msg->sadb_msg_len = -1; /* set later */
pfkey_msg->sadb_msg_reserved = 0;
pfkey_msg->sadb_msg_seq = seqno;
pfkey_msg->sadb_msg_pid = 0;
location = sizeof(struct sadb_msg);
/* SA extension */
location += build_sa_ext(&buff[location], spi,
SADB_SASTATE_MATURE, (__u8)a_type, (__u8)e_type, 0);
/* src address extension */
location += build_address_ext(&buff[location],
SADB_EXT_ADDRESS_SRC, src);
/* dst address extension */
location += build_address_ext(&buff[location],
SADB_EXT_ADDRESS_DST, dst);
len = location;
pfkey_msg->sadb_msg_len = len / IPSEC_PFKEYv2_ALIGN;
#ifdef __WIN32__
err = send(sock, (char *)pfkey_msg, len, 0);
#else
err = write(sock, pfkey_msg, len);
#endif
if (err < 1) {
fprintf(stderr, "sadb_readdress: PF_KEY write() error: %s.\n",
strerror(errno));
return(err);
}
return(0);
}
/* used to establish direction */
int pfkey_send_spdadd(int so, struct sockaddr *src, u_int prefs,
struct sockaddr *dst, u_int prefd, u_int proto,
caddr_t pol, int policylen, u_int32_t seq)
{
struct sadb_msg pfkey_msgh;
struct sadb_x_policy *policy;
int len, err=0, location;
char buff[1024];
location = 0;
len = sizeof(struct sadb_msg);
len += sizeof(struct sadb_sa);
len += 2*sizeof(struct sadb_address);
len += 2*PFKEY_ALIGN8(SALEN(src));
memset(buff, 0, len);
/* message header */
pfkey_msgh.sadb_msg_version = PF_KEY_V2;
pfkey_msgh.sadb_msg_type = SADB_X_SPDADD;
pfkey_msgh.sadb_msg_errno = 0;
pfkey_msgh.sadb_msg_satype = SADB_SATYPE_ESP;
pfkey_msgh.sadb_msg_len = len / IPSEC_PFKEYv2_ALIGN;
pfkey_msgh.sadb_msg_reserved = 0;
pfkey_msgh.sadb_msg_seq = seq;
pfkey_msgh.sadb_msg_pid = 0;
len = sizeof(struct sadb_msg);
memcpy(&buff[0], &pfkey_msgh, len);
location += len;
/* source flow extension */
location += build_address_ext( &buff[location],
SADB_EXT_ADDRESS_SRC, src);
/* destination flow extension */
location += build_address_ext( &buff[location],
SADB_EXT_ADDRESS_DST, dst);
/* policy extension - already built by ipsec_set_policy() */
policy = (struct sadb_x_policy *)&buff[location];
memcpy(policy, pol, sizeof(struct sadb_x_policy));
location += sizeof(struct sadb_x_policy);
#ifdef __WIN32__
err = send(so, buff, location, 0);
#else
err = write(so, buff, location);
#endif
if (err < 1){
fprintf(stderr, "sadb_add_policy: pfkey write() error: %s.\n",
strerror(errno));
}
return(err);
}
int pfkey_send_spddelete(int so, struct sockaddr *src, u_int prefs,
struct sockaddr *dst, u_int prefd, u_int proto,
caddr_t policy, int policylen, u_int32_t seq)
{
/* This is currently a no-op function. */
return(0);
}
int pfkey_send_delete(int so, u_int satype, u_int mode,
struct sockaddr *src, struct sockaddr *dst,
u_int32_t spi)
{
struct sadb_msg pfkey_msgh;
int len, err=0, location;
char buff[SADB_MSG_SIZE_DELETE]; /* 80 */
location = 0;
len = sizeof(struct sadb_msg);
len += sizeof(struct sadb_sa);
len += 2*sizeof(struct sadb_address);
len += 2*sizeof(struct sockaddr);
memset(buff, 0, len);
/* message header */
pfkey_msgh.sadb_msg_version = PF_KEY_V2;
pfkey_msgh.sadb_msg_type = SADB_DELETE;
pfkey_msgh.sadb_msg_errno = 0;
pfkey_msgh.sadb_msg_satype = satype;
pfkey_msgh.sadb_msg_len = len / IPSEC_PFKEYv2_ALIGN;
pfkey_msgh.sadb_msg_reserved = 0;
pfkey_msgh.sadb_msg_seq = 0;
pfkey_msgh.sadb_msg_pid = 0;
len = sizeof(struct sadb_msg);
memcpy(&buff[0], &pfkey_msgh, len);
location += len;
/* SA extension */
location += build_sa_ext(&buff[location], spi, 0, 0, 0, 0);
/* source flow extension */
location += build_address_ext(&buff[location],
SADB_EXT_ADDRESS_SRC, src);
/* destination flow extension */
location += build_address_ext(&buff[location],
SADB_EXT_ADDRESS_DST, dst);
/* send SADB_DELETE message to the kernel */
#ifdef __WIN32__
err = send(so, buff, location, 0);
#else
err = write(so, buff, location);
#endif
if (err < 1){
fprintf(stderr, "sadb_delete: pfkey write() error: %s.\n",
strerror(errno));
}
return(err);
}
int pfkey_send_register(int so, u_int satype)
{
struct sadb_msg pfkey_msgh;
int len, err=0;
memset(&pfkey_msgh, 0, sizeof(struct sadb_msg));
/* build the PF_KEY message */
pfkey_msgh.sadb_msg_version = PF_KEY_V2;
pfkey_msgh.sadb_msg_type = SADB_REGISTER;
pfkey_msgh.sadb_msg_errno = 0;
pfkey_msgh.sadb_msg_satype = satype;
pfkey_msgh.sadb_msg_len = sizeof(struct sadb_msg) / IPSEC_PFKEYv2_ALIGN;
pfkey_msgh.sadb_msg_reserved = 0;
pfkey_msgh.sadb_msg_seq = 0;
pfkey_msgh.sadb_msg_pid = 0;
len = sizeof(pfkey_msgh);
/* send SADB_REGISTER message to the kernel */
#ifdef __WIN32__
err = send(so, (char *)&pfkey_msgh, len, 0);
#else
err = write(so, &pfkey_msgh, len);
#endif
if (err < 1) {
fprintf(stderr, "sadb_register: pfkey write() error: %s.\n",
strerror(errno));
}
return(err);
}
int pfkey_send_getspi(int so, u_int satype, u_int mode,
struct sockaddr *src, struct sockaddr *dst, u_int32_t min,
u_int32_t max, u_int32_t reqid, u_int32_t seq)
{
int err, location=0, len=0;
struct sadb_msg *pfkey_msg;
struct sadb_spirange *spirange;
char buff[256];
location = 0;
/* message header */
pfkey_msg = (struct sadb_msg*) &buff[0];
pfkey_msg->sadb_msg_version = PF_KEY_V2;
pfkey_msg->sadb_msg_type = SADB_GETSPI;
pfkey_msg->sadb_msg_errno = 0;
pfkey_msg->sadb_msg_satype = satype;
pfkey_msg->sadb_msg_len = -1;
pfkey_msg->sadb_msg_reserved = 0;
pfkey_msg->sadb_msg_seq = seq;
pfkey_msg->sadb_msg_pid = 0;
len = sizeof(struct sadb_msg);
location += len;
/* spirange extension */
spirange = (struct sadb_spirange*) &buff[location];
spirange->sadb_spirange_len = \
(sizeof(struct sadb_spirange) / IPSEC_PFKEYv2_ALIGN);
spirange->sadb_spirange_exttype = SADB_EXT_SPIRANGE;
spirange->sadb_spirange_min = min;
spirange->sadb_spirange_max = max;
spirange->sadb_spirange_reserved = 0;
location += sizeof(struct sadb_spirange);
/* complete the header */
len = location;
pfkey_msg->sadb_msg_len = len / IPSEC_PFKEYv2_ALIGN;
/* send the SADB_GET message to the kernel */
#ifdef __WIN32__
err = send(so, (char *)pfkey_msg, len, 0);
#else
err = write(so, (char *)pfkey_msg, len);
#endif
if (err < 1) {
fprintf(stderr, "sadb_getspi: pfkey write() error: %s.\n",
strerror(errno));
}
return(err);
}
int pfkey_send_get(int so, u_int satype, u_int mode,
struct sockaddr *src, struct sockaddr *dst, u_int32_t spi)
{
int err, location=0, len=0;
struct sadb_msg *pfkey_msg;
char buff[256];
location = 0;
/* message header */
pfkey_msg = (struct sadb_msg*) &buff[0];
pfkey_msg->sadb_msg_version = PF_KEY_V2;
pfkey_msg->sadb_msg_type = SADB_GET;
pfkey_msg->sadb_msg_errno = 0;
pfkey_msg->sadb_msg_satype = satype;
pfkey_msg->sadb_msg_len = -1;
pfkey_msg->sadb_msg_reserved = 0;
pfkey_msg->sadb_msg_seq = 0;
pfkey_msg->sadb_msg_pid = 0;
len = sizeof(struct sadb_msg);
location += len;
/* SA extension */
location += build_sa_ext(&buff[location], spi,
SADB_SASTATE_MATURE, 0, 0, 0);
/* source address extension */
location += build_address_ext(&buff[location],
SADB_EXT_ADDRESS_SRC, src);
/* destination address extension */
location += build_address_ext(&buff[location],
SADB_EXT_ADDRESS_DST, dst);
/* complete the header */
len = location;
pfkey_msg->sadb_msg_len = len / IPSEC_PFKEYv2_ALIGN;
/* send the SADB_GET message to the kernel */
#ifdef __WIN32__
err = send(so, (char *)pfkey_msg, len, 0);
#else
err = write(so, (char *)pfkey_msg, len);
#endif
if (err < 1) {
fprintf(stderr, "sadb_get: pfkey write() error: %s.\n",
strerror(errno));
}
return(err);
}
int __ipsec_errcode;
const char *ipsec_strerror (void)
{
return(0);
}
int ipsec_get_policylen (caddr_t policy)
{
return(sizeof(struct sadb_x_policy));
}
caddr_t ipsec_set_policy (char *msg, int msglen)
{
struct sadb_x_policy *policy;
int len = sizeof(struct sadb_x_policy);
if (msglen < 2)
return NULL;
policy = (struct sadb_x_policy*) malloc(len);
memset(policy, 0, len);
policy->sadb_x_policy_exttype = SADB_X_EXT_POLICY;
policy->sadb_x_policy_len = (len / IPSEC_PFKEYv2_ALIGN);
/* direction: 2 == outgoing, 1 == incoming */
if (strncmp(msg, "in", 2)==0) {
policy->sadb_x_policy_dir = 1;
} else {
policy->sadb_x_policy_dir = 2;
}
return((caddr_t)policy);
}
/*****************************************
* Message extension builders *
*****************************************/
/*
* build an address extension
*/
int build_address_ext(char *data, int type, struct sockaddr *addr)
{
struct sadb_address *pfkey_addr;
int addr_len, len, plen;
plen = (addr->sa_family == AF_INET) ? (sizeof(struct in_addr) << 3) :
(sizeof(struct in6_addr) << 3);
addr_len = SALEN(addr);
pfkey_addr = (struct sadb_address*) data;
pfkey_addr->sadb_address_len = PFKEY_ALIGN8(sizeof(struct sadb_address)
+ addr_len) / IPSEC_PFKEYv2_ALIGN;
pfkey_addr->sadb_address_exttype = type;
pfkey_addr->sadb_address_proto = IPPROTO_ESP;
pfkey_addr->sadb_address_prefixlen = plen;
pfkey_addr->sadb_address_reserved = 0;
len = sizeof(struct sadb_address);
memcpy(&data[len], addr, addr_len);
len += addr_len;
return(PFKEY_ALIGN8(len));
}
/*
* build an identity extension
*/
int build_ident_ext(char *data, int type, struct sockaddr *addr)
{
struct sadb_ident *pfkey_ident;
int addr_len, len;
addr_len = SALEN(addr);
pfkey_ident = (struct sadb_ident*) data;
pfkey_ident->sadb_ident_len = PFKEY_ALIGN8(sizeof(struct sadb_ident) +
addr_len) / IPSEC_PFKEYv2_ALIGN;
pfkey_ident->sadb_ident_exttype = type;
pfkey_ident->sadb_ident_type = 0;
pfkey_ident->sadb_ident_reserved = 0;
pfkey_ident->sadb_ident_id = 0;
len = sizeof(struct sadb_ident);
memcpy(&data[len], addr, addr_len);
len += addr_len;
return(PFKEY_ALIGN8(len));
}
/*
* build SA extension
*/
int build_sa_ext(char *data, __u32 spi, __u8 state, __u8 auth, __u8 encrypt, __u32 flags)
{
struct sadb_sa *pfkey_sa;
pfkey_sa = (struct sadb_sa*) data;
pfkey_sa->sadb_sa_len = sizeof(struct sadb_sa) / IPSEC_PFKEYv2_ALIGN;
pfkey_sa->sadb_sa_exttype = SADB_EXT_SA;
pfkey_sa->sadb_sa_spi = spi; /* SPI is already in network byte order */
pfkey_sa->sadb_sa_replay = 0;
pfkey_sa->sadb_sa_state = state;
pfkey_sa->sadb_sa_auth = auth;
pfkey_sa->sadb_sa_encrypt = encrypt;
pfkey_sa->sadb_sa_flags = flags;
return(sizeof(struct sadb_sa));
}
/*
* build SA2 extension
*/
int build_sa2_ext(char *data, __u32 mode)
{
struct sadb_x_sa2 *pfkey_sa2;
pfkey_sa2 = (struct sadb_x_sa2*) data;
pfkey_sa2->sadb_x_sa2_len = sizeof(struct sadb_x_sa2) \
/ IPSEC_PFKEYv2_ALIGN;
pfkey_sa2->sadb_x_sa2_exttype = SADB_X_EXT_SA2;
pfkey_sa2->sadb_x_sa2_mode = (__u8)mode; /* this is all we care about */
pfkey_sa2->sadb_x_sa2_reserved1 = 0;
pfkey_sa2->sadb_x_sa2_reserved2 = 0;
pfkey_sa2->sadb_x_sa2_sequence = 0;
pfkey_sa2->sadb_x_sa2_reqid = 0;
return(sizeof(struct sadb_x_sa2));
}
/*
* build nat port extension
*/
int build_nat_port_ext(char *data, int type, __u16 port)
{
struct sadb_x_nat_t_port *pfkey_nat;
pfkey_nat = (struct sadb_x_nat_t_port*) data;
pfkey_nat->sadb_x_nat_t_port_len = sizeof(struct sadb_x_nat_t_port) \
/ IPSEC_PFKEYv2_ALIGN;
pfkey_nat->sadb_x_nat_t_port_exttype = (__u16)type;
pfkey_nat->sadb_x_nat_t_port_port = htons(port);
pfkey_nat->sadb_x_nat_t_port_reserved = 0;
return(sizeof(struct sadb_x_nat_t_port));
}
/*
* build lifetime extension
*/
int build_lifetime_ext(char *data, int type, __u32 lifetime)
{
struct sadb_lifetime *pfkey_lifetime;
pfkey_lifetime = (struct sadb_lifetime*) data;
pfkey_lifetime->sadb_lifetime_len = sizeof(struct sadb_lifetime) /
IPSEC_PFKEYv2_ALIGN;
pfkey_lifetime->sadb_lifetime_exttype = type;
pfkey_lifetime->sadb_lifetime_allocations = 0;
pfkey_lifetime->sadb_lifetime_bytes = 0;
pfkey_lifetime->sadb_lifetime_addtime = lifetime;
pfkey_lifetime->sadb_lifetime_usetime = 0;
return(sizeof(struct sadb_lifetime));
}
/*
* * build hit extension HIT_BITSIZE / 8
*/
int build_hit_ext(char *data, int type, uint16_t val)
{
struct sadb_hit *pfkey_hit;
pfkey_hit = (struct sadb_hit*) data;
pfkey_hit->sadb_hit_len = sizeof(struct sadb_hit)/IPSEC_PFKEYv2_ALIGN;
pfkey_hit->sadb_hit_exttype = type;
pfkey_hit->sadb_hit = val;
return(sizeof(struct sadb_hit));
}

390
src/protocol/hip_keymat.c Normal file
View File

@ -0,0 +1,390 @@
/*
* Host Identity Protocol
* Copyright (C) 2002-06 the Boeing Company
*
* 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 2 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.
*
* hip_keymat.c
*
* Author: Jeff Ahrenholz, <jeffrey.m.ahrenholz@boeing.com>
*
* Implements a HIP Keymat data structure for storing a
* shared secret key and it derivitives.
*
*/
#include <stdio.h>
#include <string.h>
#include <openssl/sha.h>
#include <openssl/des.h> /* DES_KEY_SZ == 8 bytes*/
#include <openssl/dsa.h>
#include <hip/hip_types.h>
#include <hip/hip_proto.h>
#include <hip/hip_globals.h>
#include <hip/hip_funcs.h>
#define MAX_KEYS 8
/*
* keys should be:
* 0 initiator HIP key (24 bytes (3DES))
* 1 responder HIP key (24 bytes (3DES))
* 2 initiator ESP key (24 bytes (3DES))
* 3 responder ESP key (24 bytes (3DES))
* 4 initiator AUTH key (20 bytes (SHA))
* 5 responder AUTH key (20 bytes (SHA))
*/
/*
* This function takes a Diffie Hellman computed key as binary input and
* stores it in the hip_a->keymat
*
*/
int set_secret_key(unsigned char *key, hip_assoc *hip_a)
{
int keylen;
if (NULL == key) {
log_(NORM, "set_secret_key() passed in null key\n");
return(-1);
}
keylen = DH_size(hip_a->dh);
if (hip_a->dh_secret)
free(hip_a->dh_secret);
hip_a->dh_secret = key;
#ifndef SMA_CRAWLER
log_(NORM, "************\nDH secret key set to:\n0x");
print_hex(hip_a->dh_secret, keylen);
log_(NORM, "\n***********\n");
#endif
return keylen;
}
/*
* get_key()
*
* IN: hip_a = contains HITs and keymat
* type = type of key to get
* peer = TRUE if you want the peer's key, FALSE for keys that
* are associated with my HIT.
* OUT: Pointer to the proper key from the keymat.
*/
unsigned char *get_key(hip_assoc *hip_a, int type, int peer)
{
int result, num=0;
result = compare_hits(hip_a->peer_hi->hit, hip_a->hi->hit);
/* result > 0 means peer HIT larger than my HIT */
switch (type) {
case HIP_ENCRYPTION:
peer ? ((result > 0) ? (num=GL_HIP_ENCRYPTION_KEY):
(num=LG_HIP_ENCRYPTION_KEY)) :
((result > 0) ? (num=LG_HIP_ENCRYPTION_KEY):
(num=GL_HIP_ENCRYPTION_KEY));
break;
case HIP_INTEGRITY:
peer ? ((result > 0) ? (num=GL_HIP_INTEGRITY_KEY):
(num=LG_HIP_INTEGRITY_KEY)) :
((result > 0) ? (num=LG_HIP_INTEGRITY_KEY):
(num=GL_HIP_INTEGRITY_KEY));
break;
case ESP_ENCRYPTION:
peer ? ((result > 0) ? (num=GL_ESP_ENCRYPTION_KEY):
(num=LG_ESP_ENCRYPTION_KEY)) :
((result > 0) ? (num=LG_ESP_ENCRYPTION_KEY):
(num=GL_ESP_ENCRYPTION_KEY));
break;
case ESP_AUTH:
peer ? ((result > 0) ? (num=GL_ESP_AUTH_KEY):
(num=LG_ESP_AUTH_KEY)) :
((result > 0) ? (num=LG_ESP_AUTH_KEY):
(num=GL_ESP_AUTH_KEY));
break;
default:
num = 0;
break;
}
return hip_a->keys[num].key;
}
/*
* This function will derive and store only the required HIP keys
* (ESP keys are computed later)
*/
void compute_keys(hip_assoc *hip_a)
{
compute_keymat(hip_a);
draw_keys(hip_a, TRUE, 0);
}
/*
* Compute a new keymat based on the DH secret Kij and HITs
*/
int compute_keymat(hip_assoc *hip_a)
{
int i, result;
int location, len, dh_secret_len, hashdata_len;
char *hashdata;
unsigned char hash[SHA_DIGEST_LENGTH], last_byte = 1;
BIGNUM *hit1, *hit2;
hip_hit *hitp;
SHA_CTX c;
if (hip_a==NULL) {
log_(NORM, "no hip_a in compute_keymat()\n");
return(-1);
}
hitp = &(hip_a->peer_hi->hit);
if (hitp==NULL) {
log_(NORM, "no peer HIT in compute_keymat()\n");
return(-1);
}
hit1 = BN_bin2bn((unsigned char*)hitp, HIT_SIZE, NULL);
hit2 = BN_bin2bn((unsigned char*)hip_a->hi->hit, HIT_SIZE, NULL);
result = BN_ucmp(hit1, hit2);
/* Kij */
dh_secret_len = DH_size(hip_a->dh);
hashdata_len = dh_secret_len + (2*HIT_SIZE) + (2*sizeof(__u64)) + 1;
hashdata = malloc(hashdata_len);
memcpy(hashdata, hip_a->dh_secret, dh_secret_len);
location = dh_secret_len;
/* sort(Resp-HIT, Init-HIT) */
if (result <= 0) { /* hit1 <= hit2 */
memcpy(&hashdata[location], hitp, HIT_SIZE);
location += HIT_SIZE;
memcpy(&hashdata[location],
hip_a->hi->hit, HIT_SIZE);
location += HIT_SIZE;
} else { /* hit1 > hit2 */
memcpy(&hashdata[location],
hip_a->hi->hit, HIT_SIZE);
location += HIT_SIZE;
memcpy(&hashdata[location], hitp, HIT_SIZE);
location += HIT_SIZE;
}
/* I | J */
memcpy(&hashdata[location], &hip_a->cookie_r.i, sizeof(__u64));
location += sizeof(__u64);
memcpy(&hashdata[location], &hip_a->cookie_j, sizeof(__u64));
location += sizeof(__u64);
/* 1 */
memcpy(&hashdata[location], &last_byte, sizeof(last_byte));
location += sizeof(last_byte);
/* SHA1 hash the concatenation */
SHA1_Init(&c);
SHA1_Update(&c, hashdata, location);
SHA1_Final(hash, &c);
memcpy(hip_a->keymat, hash, SHA_DIGEST_LENGTH);
location = SHA_DIGEST_LENGTH;
/* compute K2 ... K38
* 768 bytes / 20 bytes per hash = 38 loops
* this is enough space for 32 ESP keys
*/
for (i = 1; i < (KEYMAT_SIZE/SHA_DIGEST_LENGTH); i++) {
last_byte++;
memcpy(hashdata, hip_a->dh_secret, dh_secret_len); /* Kij */
len = dh_secret_len;
memcpy(&hashdata[len], hash, SHA_DIGEST_LENGTH); /* K_i) */
len += SHA_DIGEST_LENGTH;
memcpy(&hashdata[len], &last_byte, sizeof(last_byte)); /* i+1 */
len += sizeof(last_byte);
SHA1_Init(&c);
SHA1_Update(&c, hashdata, len);
SHA1_Final(hash, &c);
/* accumulate the keying material */
memcpy(&hip_a->keymat[location], hash, SHA_DIGEST_LENGTH);
location += SHA_DIGEST_LENGTH;
}
free(hashdata);
BN_free(hit1);
BN_free(hit2);
return(0);
}
int draw_keys(hip_assoc *hip_a, int draw_hip_keys, int keymat_index)
{
int location, i, k, max, key_type, len;
if (hip_a==NULL) {
log_(NORM, "no hip_a in draw_keys()\n");
return(-1);
}
/* erase new key locations */
if (draw_hip_keys) {
i = 0;
k = 0;
max = GL_ESP_ENCRYPTION_KEY;
} else {
i = GL_ESP_ENCRYPTION_KEY;
k = GL_ESP_ENCRYPTION_KEY;
max = NUMKEYS;
}
for (; i < max; i++) {
memset(hip_a->keys[i].key, 0, HIP_KEY_SIZE);
hip_a->keys[i].length = 0;
hip_a->keys[i].type = 0;
}
log_(NORM, "Using HIP transform of %d", hip_a->hip_transform);
if (draw_hip_keys) {
log_(NORM, ".\nDrawing new HIP encryption/integrity keys:\n");
} else {
log_(NORM, " ESP transform of %d.\nDrawing new ESP keys from "
"keymat index %d:\n", hip_a->esp_transform, keymat_index);
}
location = keymat_index;
/* draw keys from the keymat */
for (; k < max; k++) {
/* decide what type/length of key to use */
switch(k) {
case GL_HIP_ENCRYPTION_KEY: /* ENCRYPTED payload keys */
case LG_HIP_ENCRYPTION_KEY:
key_type = hip_a->hip_transform;
len = enc_key_len(key_type);
break;
case GL_HIP_INTEGRITY_KEY: /* HMAC keys */
case LG_HIP_INTEGRITY_KEY:
key_type = hip_a->hip_transform;
len = auth_key_len(key_type);
break;
case GL_ESP_ENCRYPTION_KEY: /* ESP encryption keys */
case LG_ESP_ENCRYPTION_KEY:
key_type = hip_a->esp_transform;
len = enc_key_len(key_type);
break;
case GL_ESP_AUTH_KEY: /* ESP authentication keys */
case LG_ESP_AUTH_KEY:
key_type = hip_a->esp_transform;
len = auth_key_len(key_type);
break;
default:
key_type = 0; /* no key */
len = 0;
break;
}
/* load the key */
hip_a->keys[k].type = key_type;
hip_a->keys[k].length = len;
if ((location + len) > KEYMAT_SIZE) {
log_(NORM, "No more keymat material for key %d!\n", k);
return(-1);
}
log_(NORM, "Key %d (%d,%d) keymat[%3d] 0x",
k, key_type, len, location);
if (len) {
memcpy(hip_a->keys[k].key,
&hip_a->keymat[location], len);
location += len;
}
print_hex(hip_a->keys[k].key, len);
log_(NORM, "\n");
}
hip_a->keymat_index = location;
return(location);
}
int draw_mr_key(hip_assoc *hip_a, int keymat_index)
{
int location, key_type, len;
if (hip_a==NULL) {
log_(NORM, "no hip_a in draw_mr_key()\n");
return(-1);
}
location = keymat_index;
key_type = hip_a->hip_transform;
len = auth_key_len(key_type);
hip_a->mr_key.type = key_type;
hip_a->mr_key.length = len;
if ((location + len) > KEYMAT_SIZE) {
log_(NORM, "No more keymat material for mobile router key!\n");
return(-1);
}
log_(NORM, "Mobile router key (%d,%d) keymat[%3d] 0x",
key_type, len, location);
if (len) {
memcpy(hip_a->mr_key.key, &hip_a->keymat[location], len);
location += len;
}
print_hex(hip_a->mr_key.key, len);
log_(NORM, "\n");
hip_a->keymat_index = location;
return(location);
}
int auth_key_len(int suite_id)
{
switch (suite_id) {
case ESP_AES_CBC_HMAC_SHA1:
case ESP_3DES_CBC_HMAC_SHA1:
case ESP_BLOWFISH_CBC_HMAC_SHA1:
case ESP_NULL_HMAC_SHA1:
return(KEY_LEN_SHA1);
case ESP_3DES_CBC_HMAC_MD5:
case ESP_NULL_HMAC_MD5:
return(KEY_LEN_MD5);
default:
break;
}
return(0);
}
int enc_key_len(int suite_id)
{
switch (suite_id){
case ESP_AES_CBC_HMAC_SHA1:
return(KEY_LEN_AES);
case ESP_3DES_CBC_HMAC_SHA1:
case ESP_3DES_CBC_HMAC_MD5:
return(KEY_LEN_3DES);
case ESP_BLOWFISH_CBC_HMAC_SHA1:
return(KEY_LEN_BLOWFISH);
case ESP_NULL_HMAC_SHA1:
case ESP_NULL_HMAC_MD5:
return(KEY_LEN_NULL);
default:
break;
}
return(0);
}
int enc_iv_len(int suite_id)
{
switch (suite_id){
case ESP_AES_CBC_HMAC_SHA1:
return(16); /* AES uses 128-bit IV */
case ESP_3DES_CBC_HMAC_SHA1:
case ESP_3DES_CBC_HMAC_MD5:
case ESP_BLOWFISH_CBC_HMAC_SHA1:
return(8); /* 64-bit IV */
case ESP_NULL_HMAC_SHA1:
case ESP_NULL_HMAC_MD5:
return(0);
default:
break;
}
return(0);
}

1667
src/protocol/hip_main.c Normal file

File diff suppressed because it is too large Load Diff

2447
src/protocol/hip_output.c Normal file

File diff suppressed because it is too large Load Diff

315
src/protocol/hip_status.c Normal file
View File

@ -0,0 +1,315 @@
/*
* Host Identity Protocol
* Copyright (C) 2002-06 the Boeing Company
*
* 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 2 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.
*
* hip_status.c
*
* Author: Jeff Ahrenholz, <jeffrey.m.ahrenholz@boeing.com>
*
* Status socket support, handles requests from an external status
* program.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#ifdef __WIN32__
#include <winsock2.h>
#include <ws2tcpip.h>
#include <win32/types.h>
#include <io.h>
#else
#include <unistd.h>
#include <sys/time.h>
#ifdef __MACOSX__
#include <netinet/in_systm.h>
#endif
#include <netinet/in.h> /* INADDR_NONE */
#include <netinet/ip.h> /* INADDR_NONE */
#endif
#include <openssl/sha.h>
#include <openssl/dsa.h>
#include <openssl/asn1.h>
#include <openssl/rand.h>
#include <sys/types.h>
#include <errno.h>
#include <fcntl.h> /* open() */
#ifdef __MACOSX__
#include <sys/types.h>
#else
#ifndef __WIN32__
#include <asm/types.h>
#endif
#endif
#ifndef __WIN32__
#include <netinet/ip6.h>
#endif
#include <hip/hip_types.h>
#include <hip/hip_proto.h>
#include <hip/hip_globals.h>
#include <hip/hip_funcs.h>
#include <hip/hip_status.h>
/* Local definitions */
#ifndef IN_LOOPBACK
#define IN_LOOPBACK(a) ((((long int) (a)) & 0xff000000) == 0x7f000000)
#endif
/* Local functions */
int status_dump_hi_list(char *buff, hi_node *list, int do_addr);
int status_dump_addr_list(char *buff, sockaddr_list *addrs);
int status_dump_assoc(char *buff);
int status_dump_opts(char *buff);
void status_set_opts(__u8 *buff);
int hip_status_open()
{
struct sockaddr_in addr;
if (s_stat)
#ifdef __WIN32__
closesocket(s_stat);
if ((s_stat = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP))==INVALID_SOCKET)
return(-1);
#else
close(s_stat);
if ((s_stat = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
return(-1);
#endif
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_port = htons(STATUS_PORT);
if (bind(s_stat, (struct sockaddr*)&addr, sizeof(addr)) < 0)
return(-1);
return(0);
}
void hip_handle_status_request(__u8 *buff, int len, struct sockaddr *addr)
{
__u16 type;
__u32 ip;
char out[1500];
int outlen=0;
struct status_tlv *tlv_end;
/* For security purposes, only allow loopback connections
* to status socket
*/
if (!addr)
return;
if (addr->sa_family == AF_INET) {
ip = ntohl(((struct sockaddr_in*)addr)->sin_addr.s_addr);
if (!IN_LOOPBACK(ip))
return;
} else {
if (!IN6_IS_ADDR_LOOPBACK(
&((struct sockaddr_in6*)addr)->sin6_addr) )
return;
}
memcpy(&type, buff, 2);
type = ntohs(type);
if ((type < HIP_STATUS_REQ_MAX) && (len != 4))
return;
switch(type) {
case HIP_STATUS_REQ_PEERS:
outlen = status_dump_hi_list(out, peer_hi_head, TRUE);
break;
case HIP_STATUS_REQ_MYIDS:
outlen = status_dump_hi_list(out, my_hi_head, FALSE);
break;
case HIP_STATUS_REQ_MYADDRS:
outlen = status_dump_addr_list(out, my_addr_head);
break;
case HIP_STATUS_REQ_ASSOC:
outlen = status_dump_assoc(out);
break;
case HIP_STATUS_REQ_OPTS:
outlen = status_dump_opts(out);
break;
case HIP_STATUS_REQ_CONF:
break;
case HIP_STATUS_CONFIG_OPTS:
status_set_opts(&buff[sizeof(struct status_tlv)]);
outlen = 0;
break;
case HIP_STATUS_REQ_MIN:
case HIP_STATUS_REQ_MAX:
default:
return;
}
if (outlen) {
tlv_end = (struct status_tlv*) &out[outlen];
tlv_end->tlv_type = htons(HIP_STATUS_REPLY_DONE);
tlv_end->tlv_len = 0;
outlen += sizeof(struct status_tlv);
len = sendto(s_stat, out, outlen, 0, addr, SALEN(addr));
}
}
/*
* reply with:
* hi
* addrlist
* hi
* addrlist
* ...
*/
int status_dump_hi_list(char *buff, hi_node *list, int do_addr)
{
struct status_tlv *t = (struct status_tlv*) buff;
char *p;
hi_node *hi;
int total_len=0, len;
__u32 lsi;
for (hi = list; hi; hi=hi->next) {
len = 0;
p = (char *)(t+1);
/* HI node */
t->tlv_type = htons(HIP_STATUS_REPLY_HI);
ADD_ITEM(p, hi->hit, len);
lsi = ((struct sockaddr_in*)&hi->lsi)->sin_addr.s_addr;
ADD_ITEM(p, lsi, len);
ADD_ITEM(p, hi->size, len);
ADD_ITEM(p, hi->r1_gen_count, len);
ADD_ITEM(p, hi->update_id, len);
ADD_ITEM(p, hi->algorithm_id, len);
strncpy(&p[len], hi->name, MAX_HI_NAMESIZE);
len += strlen(hi->name);
/* add anonymous, allow_incoming, skip_addrcheck here */
t->tlv_len = htons((__u16)len);
len += sizeof(struct status_tlv*);
if (do_addr) { /* address list */
len += status_dump_addr_list( ((char*)t) + len,
&hi->addrs);
}
t = (struct status_tlv*) (((char*)t) + len);
total_len += len;
}
return(total_len);
}
int status_dump_addr_list(char *buff, sockaddr_list *addrs)
{
struct status_tlv *t = (struct status_tlv*) buff;
sockaddr_list *a;
char *p = (char*)(t+1);
int len=0;
t->tlv_type = htons(HIP_STATUS_REPLY_ADDR);
for (a = addrs; a; a=a->next) {
ADD_ITEM(p, a->addr, len)
}
t->tlv_len = htons((__u16)len);
len += sizeof(struct status_tlv);
return(len);
}
int status_dump_assoc(char *buff)
{
struct status_tlv *t = (struct status_tlv*) buff;
hip_assoc *a;
char *p;
int total_len=0, len, i;
for (i=0; i < max_hip_assoc; i++) {
a = &hip_assoc_table[i];
/* skip empty entries */
if (a->state == UNASSOCIATED)
continue;
len = 0;
p = (char *)(t+1);
t->tlv_type = htons(HIP_STATUS_REPLY_ASSOC);
ADD_ITEM(p, a->state, len);
ADD_ITEM(p, a->state_time.tv_sec, len);
ADD_ITEM(p, a->spi_in, len);
ADD_ITEM(p, a->spi_out, len);
ADD_ITEM(p, a->hip_transform, len);
ADD_ITEM(p, a->esp_transform, len);
ADD_ITEM(p, a->dh_group_id, len);
t->tlv_len = htons((__u16)len);
len += sizeof(struct status_tlv*);
len += status_dump_hi_list( ((char*)t)+len,
a->hi, TRUE);
len += status_dump_hi_list( ((char*)t)+len,
a->peer_hi, TRUE);
/* These items not sent:
cookie, rexmt_cache, opaque, rekey, peer_rekey, keys */
t = (struct status_tlv*) (((char*)t) + len);
total_len += len;
}
return(total_len);
}
int status_dump_opts(char *buff)
{
struct status_tlv *t = (struct status_tlv*) buff;
char *p = (char *)(t+1);
int len = 0;
unsigned int opts;
t->tlv_type = htons(HIP_STATUS_REPLY_OPTS);
/* boolean options are encoded as bits in an 32-bit unsigned value */
opts = (OPT.debug == D_VERBOSE);
opts |= (OPT.debug_R1 == D_VERBOSE) << 1;
opts |= (OPT.no_retransmit == TRUE) << 2;
opts |= (OPT.opportunistic == TRUE) << 3;
opts |= (OPT.permissive == TRUE) << 4;
ADD_ITEM(p, opts, len);
t->tlv_len = htons((__u16)len);
return (len + sizeof(struct status_tlv*));
}
void status_set_opts(__u8 *buff)
{
unsigned int opts;
memcpy(&opts, buff, sizeof(unsigned int));
if (opts & 0x0001)
OPT.debug = D_VERBOSE;
else
OPT.debug = D_DEFAULT;
if ((opts >> 1) & 0x0001)
OPT.debug_R1 = D_VERBOSE;
else
OPT.debug_R1 = D_QUIET;
if ((opts >> 2) & 0x0001)
OPT.no_retransmit = TRUE;
else
OPT.no_retransmit = FALSE;
if ((opts >> 3) & 0x0001)
OPT.opportunistic = TRUE;
else
OPT.opportunistic = FALSE;
if ((opts >> 4) & 0x0001)
OPT.permissive = TRUE;
else
OPT.permissive = FALSE;
log_hipopts();
}

2566
src/protocol/hip_stun.c Normal file

File diff suppressed because it is too large Load Diff

327
src/protocol/hip_stun_udp.c Normal file
View File

@ -0,0 +1,327 @@
/*
* Host Identity Protocol
*
* STUN client based on the code provided by Vovida Networks, Inc.
* (see end of file)
* Translated from C++ code to C code by Vivien Schmitt
*
* hip_stun_udp.c
*
* Author : Vivien Schmitt, <schmitt@netlab.nec.de>
*
* STUN client used for NAT detection
*
*/
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <time.h>
#ifdef __WIN32__
#include <win32/types.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <win32/ip.h>
#else
#include <arpa/inet.h>
#include <unistd.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <netdb.h>
#endif /* __WIN32__ */
#include <fcntl.h>
#include <sys/types.h>
#include <string.h>
#include <hip/hip_stun_udp.h>
#ifdef __WIN32__
#define EADDRINUSE WSAEADDRINUSE
#define EADDRNOTAVAIL WSAEADDRNOTAVAIL
#define ENOTSOCK WSAENOTSOCK
#define ECONNRESET WSAECONNRESET
#define ECONNREFUSED WSAECONNREFUSED
#define EHOSTDOWN WSAEHOSTDOWN
#define EHOSTUNREACH WSAEHOSTUNREACH
#define EAFNOSUPPORT WSAEAFNOSUPPORT
#else
int closesocket( int fd ) { return close(fd); };
#endif
int getErrno() { return errno; }
int
openPort( unsigned short port, unsigned int interfaceIp, int verbose )
{
int fd;
struct sockaddr_in addr;
fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
if ( fd == INVALID_SOCKET )
{
int err = getErrno();
fprintf (stderr, "Could not create a UDP socket: %u \n", err);
return INVALID_SOCKET;
}
memset((char*) &(addr),0, sizeof((addr)));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_port = htons(port);
if ( (interfaceIp != 0) &&
( interfaceIp != 0x100007f ) )
{
addr.sin_addr.s_addr = htonl(interfaceIp);
if (verbose )
{
printf ("Binding to interface 0x%x\n", htonl(interfaceIp));
}
}
if ( bind( fd,(struct sockaddr*)&addr, sizeof(addr)) != 0 )
{
int e = getErrno();
switch (e)
{
case 0:
{
fprintf (stderr, "Could not bind socket\n");
return INVALID_SOCKET;
}
case EADDRINUSE:
{
fprintf(stderr, "Port %u for receiving UDP is in use\n", port);
return INVALID_SOCKET;
}
break;
case EADDRNOTAVAIL:
{
if ( verbose )
{
fprintf (stderr, "Cannot assign requested address\n");
}
return INVALID_SOCKET;
}
break;
default:
{
fprintf ( stderr, "Could not bind UDP receive port. Error=%u %s\n",
e, strerror(e));
return INVALID_SOCKET;
}
break;
}
}
if ( verbose )
{
printf("Opened port %u with fd %u\n", port, fd);
}
assert( fd != INVALID_SOCKET );
return fd;
}
int
getMessage( int fd, char* buf, int* len,
unsigned int* srcIp, unsigned short* srcPort,
int verbose)
{
int originalSize = *len;
struct sockaddr_in from;
int fromLen;
assert( fd != INVALID_SOCKET );
assert( originalSize > 0 );
fromLen = sizeof(from);
*len = recvfrom(fd,
buf,
originalSize,
0,
(struct sockaddr *)&from,
(socklen_t*)&fromLen);
if ( *len == SOCKET_ERROR )
{
int err = getErrno();
switch (err)
{
case ENOTSOCK:
fprintf (stderr, "Error fd not a socket\n");
break;
case ECONNRESET:
fprintf (stderr, "Error connection reset - host not reachable\n");
break;
default:
fprintf(stderr, "Socket Error= %u\n", err);
}
return FALSE;
}
if ( *len < 0 )
{
printf("socket closed? negative len\n");
return FALSE;
}
if ( *len == 0 )
{
printf("socket closed? zero len\n");
return FALSE;
}
*srcPort = ntohs(from.sin_port);
*srcIp = ntohl(from.sin_addr.s_addr);
if ( (*len)+1 >= originalSize )
{
if (verbose)
{
printf("Received a message that was too large\n");
}
return FALSE;
}
buf[*len]=0;
return TRUE;
}
int
sendMessage( int fd, char* buf, int l,
unsigned int dstIp, unsigned short dstPort,
int verbose)
{
struct sockaddr_in to;
int toLen;
int s, e;
assert( fd != INVALID_SOCKET );
if ( dstPort == 0 )
{
/* sending on a connected port */
assert( dstIp == 0 );
s = send(fd,buf,l,0);
}
else
{
assert( dstIp != 0 );
assert( dstPort != 0 );
toLen = sizeof(to);
memset(&to,0,toLen);
to.sin_family = AF_INET;
to.sin_port = htons(dstPort);
to.sin_addr.s_addr = htonl(dstIp);
s = sendto(fd, buf, l, 0,(struct sockaddr*)&to, toLen);
}
if ( s == SOCKET_ERROR )
{
e = getErrno();
switch (e)
{
case ECONNREFUSED:
case EHOSTDOWN:
case EHOSTUNREACH:
{
/* quietly ignore this */
}
break;
case EAFNOSUPPORT:
{
fprintf(stderr, "err EAFNOSUPPORT in send\n");
}
break;
default:
{
fprintf(stderr, "err %u %s in send.\n", e, strerror(e) );
}
}
return FALSE;
}
if ( s == 0 )
{
fprintf(stderr, "no data sent in send\n");
return FALSE;
}
if ( s != l )
{
if (verbose)
{
fprintf(stderr, "only %u out of %u bytes sent\n", s, l);
}
return FALSE;
}
return TRUE;
}
/* ====================================================================
* The Vovida Software License, Version 1.0
*
* Copyright (c) 2000 Vovida Networks, Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The names "VOCAL", "Vovida Open Communication Application Library",
* and "Vovida Open Communication Application Library (VOCAL)" must
* not be used to endorse or promote products derived from this
* software without prior written permission. For written
* permission, please contact vocal@vovida.org.
*
* 4. Products derived from this software may not be called "VOCAL", nor
* may "VOCAL" appear in their name, without prior written
* permission of Vovida Networks, Inc.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
* NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA
* NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
* IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*
* ====================================================================
*
* This software consists of voluntary contributions made by Vovida
* Networks, Inc. and many individuals on behalf of Vovida Networks,
* Inc. For more information on Vovida Networks, Inc., please see
* <http://www.vovida.org/>.
*
*/

207
src/protocol/i3_recv.c Normal file
View File

@ -0,0 +1,207 @@
/*
* Implementation of Hi3 receiver
* Author: (c) Andrei Gurtov, HIIT
* Licence: GPLv2
* Based on a modified example from UCB i3
* Written: 3.3.2005
*/
#include <hip/i3_hip.h>
/*
* Called from i3 when a data packet arrives to a trigger
* Creates msg envelop and passes the packet to HIP
*/
void receive_payload(cl_trigger *t, void* data, void *fun_ctx) {
#ifdef HI3_DEBUG
int i;
#endif
struct msghdr msg;
struct iovec iov;
cl_buf* clb = (cl_buf *) data;
#if 0
/* This is for the case when IP header is not tunneled through i3
and needs to be reconstructed for interfacing with HIP at the receiver
*/
struct ip *iph;
char buf[2000];
hiphdr *hiph;
int dglen;
struct in_addr srcaddr, dstaddr;
struct sockaddr_in src, dst;
struct hostent *hptr;
struct utsname myname;
srcaddr.s_addr = inet_addr("128.214.112.3");
dstaddr.s_addr = inet_addr("128.214.112.2");
uname(&myname);
hptr = gethostbyname(myname.nodename);
dstaddr.s_addr = *((in_addr_t *)hptr->h_addr_list[0]);
src.sin_addr = (struct in_addr) srcaddr;
src.sin_family = AF_INET;
dst.sin_addr = (struct in_addr) dstaddr;
dst.sin_family = AF_INET;
memset(buf, 0, sizeof(buf));
printf("Received %d bytes through I3\n", clb->data_len);
for (i=0; i < clb->data_len; i++)
printf("%.2x ", (unsigned char)clb->data[i]);
printf("\n");
iph = (struct ip *) buf;
hiph = (hiphdr *) ((char *)iph + sizeof(struct ip));
memcpy((char *)iph + sizeof(struct ip), clb->data, clb->data_len);
dglen = sizeof(struct ip) + clb->data_len;
iph->ip_v = 4;
iph->ip_hl = sizeof(struct ip) >> 2;
iph->ip_tos = 0;
iph->ip_len = htons(dglen); /* network byte order */
iph->ip_id = 0; /* let IP set this */
iph->ip_off = 0; /* frag offset, MF and DF flags */
iph->ip_ttl = 200;
iph->ip_p = 99;
iph->ip_src = srcaddr;
iph->ip_dst = dstaddr;
iph->ip_sum = in_cksum((unsigned short *)iph, sizeof (struct ip));
hiph->checksum = 0;
hiph->checksum = checksum_packet((char *)hiph,
(struct sockaddr *) &src,
(struct sockaddr *) &dst);
#endif
#ifdef HI3_DEBUG
printf("Passing following packet of %d to HIP\n", clb->data_len);
for (i=0; i < clb->data_len; i++)
printf("%.2x ", ((unsigned char *) clb->data)[i]);
printf("\n");
#endif
//Construct message envelop as required by hip_handle_packet()
msg.msg_name = NULL;
msg.msg_namelen = 0;
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
msg.msg_control = NULL;
msg.msg_controllen = 0;
msg.msg_flags = 0;
iov.iov_len = clb->data_len;
iov.iov_base = clb->data;
hip_handle_packet(&msg, clb->data_len, AF_INET);
}
/*
* Initialize i3 trigger from ascii string
*/
void init_id_fromstr(ID *id, char *name) {
uint i;
for (i = 0; i < ID_LEN; i++)
id->x[i] = name[i % strlen(name)];
}
/*
* i3 callbacks for trigger management
*/
void constraint_failed(cl_trigger *t, void *data, void *fun_ctx) {
printf("Trigger constraint failed\n");
}
void trigger_inserted(cl_trigger *t, void *data, void *fun_ctx) {
printf("Trigger inserted\n");
}
void trigger_failure(cl_trigger *t, void *data, void *fun_ctx) {
printf("Trigger failed\n");
/* reinsert trigger */
cl_insert_trigger(t, 0);
}
/*
* Initialize i3, insert trigger chain for host's HIT
*/
int i3_init(hip_hit *hit) {
struct hostent *hptr;
struct utsname myname;
char str[INET6_ADDRSTRLEN];
char **pptr;
cl_trigger *t1, *t;
ID id, ida;
Key key;
if (uname(&myname) < 0) {
err_sys("uname error.\n");
exit(-1);
}
if ((hptr = gethostbyname(myname.nodename)) == NULL) {
err_sys("gethostbyname error\n");
exit(-1);
}
printf("name = %s\n", hptr->h_name);
for (pptr = hptr->h_addr_list; *pptr != NULL; pptr++) {
printf("address = %s\n", inet_ntop(hptr->h_addrtype,
*pptr, str, sizeof(str)));
}
/* initialize context */
cl_init(CFGFILE);
/*
* Create and insert triggers (id, ida), and (ida, R), respectively.
* All triggers are r-constrained (right constrained)
*/
bzero(&id, ID_LEN);
memcpy(&id, hit, HIT_SIZE);
init_id_fromstr(&ida, "this is another test id");
cl_set_private_id(&id);
cl_set_private_id(&ida);
/* Note: ida will be updated as ida.key = h_r(id.key) */
t1 = cl_create_trigger_id(&id, ID_LEN_BITS, &ida,
CL_TRIGGER_CFLAG_R_CONSTRAINT);
t = cl_create_trigger(&ida, ID_LEN_BITS, &key,
CL_TRIGGER_CFLAG_R_CONSTRAINT);
/* associate callbacks with the inserted trigger */
cl_register_trigger_callback(t, CL_CBK_TRIGGER_CONSTRAINT_FAILED,
constraint_failed, NULL);
cl_register_trigger_callback(t, CL_CBK_RECEIVE_PAYLOAD,
receive_payload, NULL);
cl_register_trigger_callback(t, CL_CBK_TRIGGER_INSERTED,
trigger_inserted, NULL);
cl_register_trigger_callback(t, CL_CBK_TRIGGER_REFRESH_FAILED,
trigger_failure, NULL);
/* insert triggers */
cl_insert_trigger(t, 0);
cl_insert_trigger(t1, 0);
printf("Listening to HIT in I3: ");
print_hit((const hip_hit*) hit);
printf("\n");
printf("Public trigger");
printf_i3_id(&id, 2);
printf("Private trigger");
printf_i3_id(&ida, 2);
return 0;
}
/*
* Removes i3 triggers
*/
void clean_i3(cl_trigger *t1, cl_trigger *t) {
/* remove & destroy trigger */
cl_destroy_trigger(t);
cl_destroy_trigger(t1);
/* destroy context */
cl_exit();
}

142
src/protocol/i3_send.c Normal file
View File

@ -0,0 +1,142 @@
/*
* Implementation of Hi3 sender
* Author: (c) Andrei Gurtov, HIIT
* Licence: GPLv2
* Modified example from UCB i3
* Written: 10.2.2005
*/
#include <hip/i3_hip.h>
/*
* Prints out HIT for debugging
*/
void print_hit(const hip_hit *hit) {
int i;
unsigned char *c;
c = (unsigned char*) hit;
printf("0x");
for (i=0; i < HIT_SIZE; i++) {
printf("%.2x", c[i]);
}
}
/*
* Create i3 trigger id from ascii hex string
*/
void read_id(ID *id, char *hstr) {
int i;
char h[3];
int dummy;
for (i = 0; i < ID_LEN; i++) {
/* covert from string into hexa number */
h[0] = hstr[2*i];
h[1] = hstr[2*i + 1];
h[2] = 0;
sscanf(h, "%x", &dummy);
id->x[i] = dummy;
}
}
/*
* Calculate checksum for IP header, example from Stevens
*/
unsigned short in_cksum(unsigned short *addr, int len) {
int nleft = len;
int sum = 0;
unsigned short *w = addr;
unsigned short answer = 0;
/*
* Our algorithm is simple, using a 32 bit accumulator (sum), we add
* sequential 16 bit words to it, and at the end, fold back all the
* carry bits from the top 16 bits into the lower 16 bits.
*/
while (nleft > 1) {
sum += *w++;
nleft -= 2;
}
/* 4mop up an odd byte, if necessary */
if (nleft == 1) {
*(unsigned char *)(&answer) = *(unsigned char *)w ;
sum += answer;
}
/* 4add back carry outs from top 16 bits to low 16 bits */
sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */
sum += (sum >> 16); /* add carry */
answer = ~sum; /* truncate to 16 bits */
return(answer);
}
/*
* Callback for i3
*/
void no_matching_trigger(void *ctx_data, void *data, void *fun_ctx) {
ID *id = (ID *) ctx_data;
printf("Following ID not found, ");
printf_i3_id(id, 0);
}
/*
* Send a packet to i3 assuming the responder's hit is inserted as a trigger
*/
int send_i3(__u8 *data, int size, hip_hit *hit, struct sockaddr* src,
struct sockaddr* dst) {
ID id;
cl_buf *clb;
struct ip *iph;
int dglen;
#ifdef HI3_DEBUG
int i;
#endif
dglen = size + sizeof(struct ip);
clb = cl_alloc_buf(dglen);
iph = (struct ip *) clb->data;
memcpy((char *)iph + sizeof(struct ip), data, size);
/* create IP header for tunneling HIP packet through i3 */
iph->ip_v = 4;
iph->ip_hl = sizeof(struct ip) >> 2;
iph->ip_tos = 0;
iph->ip_len = htons(dglen); /* network byte order */
iph->ip_id = 0; /* let IP set this */
iph->ip_off = 0; /* frag offset, MF and DF flags */
iph->ip_ttl = 200;
iph->ip_p = 99;
iph->ip_src = ((struct sockaddr_in *)src)->sin_addr;
iph->ip_dst = ((struct sockaddr_in *)dst)->sin_addr;
iph->ip_sum = in_cksum((unsigned short *)iph, sizeof (struct ip));
clb->data_len = dglen;
bzero(&id, ID_LEN);
memcpy(&id, hit, HIT_SIZE);
cl_set_private_id(&id);
/* exception when matching trigger not found */
cl_register_callback(CL_CBK_TRIGGER_NOT_FOUND, no_matching_trigger, NULL);
printf("Responder's HIT for I3: ");
print_hit((const hip_hit*) hit);
printf("\n");
printf_i3_id(&id, 2);
#ifdef HI3_DEBUG
printf("Passing following packet of %d to i3\n", clb->data_len);
for (i=0; i < clb->data_len; i++)
printf("%.2x ", ((unsigned char *) clb->data)[i]);
printf("\n");
#endif
cl_send(&id, clb, 0);
cl_free_buf(clb);
return size;
}

520
src/protocol/listen.c Normal file
View File

@ -0,0 +1,520 @@
/*
* Host Identity Protocol
* Copyright (C) 2002-04 The Boeing Company
*
* 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 2 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.
*
* listen.c
*
* Author: Jeff Ahrenholz, <jeffrey.m.ahrenholz@boeing.com>
*
* Listens for PF_KEY messages and prints their field values.
*
*/
#include <stdio.h> /* stderr, etc */
#include <stdlib.h> /* rand() */
#include <errno.h> /* strerror(), errno */
#include <string.h> /* memset() */
#include <time.h> /* time() */
#include <ctype.h> /* tolower() */
#include <arpa/inet.h> /* inet_addr() */
#include <sys/socket.h> /* sock(), recvmsg(), etc */
#include <sys/types.h> /* getpid() support, etc */
#include <unistd.h> /* getpid() */
#include <netinet/in.h> /* struct sockaddr_in, etc */
//#include <linux/ipsec.h>
#include "/usr/src/linux/include/linux/pfkeyv2.h" /* PF_KEY_V2 support */
#include "hip.h"
#define IPSEC_PFKEYv2_ALIGN (sizeof(uint64_t) / sizeof(uint8_t))
/* local functions */
char * ip_to_s(__u32 ip);
int print_address(char* buff, struct sadb_address* addr);
int print_sa(char* buff, struct sadb_sa* sa);
int main(int argc, char *argv[])
{
int s_pfk;
fd_set read_fdset;
fd_set excp_fdset;
struct timeval timeout;
struct msghdr msg;
struct iovec iov;
struct sockaddr_in addr;
char buff[2048];
char obuff[1024];
int buff_len = sizeof(buff);
int err=0;
printf("== %s started ==\n",argv[0]);
/* create required sockets */
{
addr.sin_family = AF_INET;
/*
addr.sin_port = htons(H_PORT);
*/
addr.sin_addr.s_addr = htonl(INADDR_ANY);
s_pfk = socket(PF_KEY, SOCK_RAW, PF_KEY_V2);
if (s_pfk < 0){
fprintf(stderr, "socket() failed, maybe you need FreeS/WAN's KLIPS?\n");
fprintf(stderr, "%s.\n", strerror(errno));
return(-1);
}
}
/* register PF_KEY types with kernel */
{
err = sadb_register_old(s_pfk, SADB_SATYPE_ESP);
if (err > 0) {
printf("Registered PF_KEY ESP type with kernel.\n");
}
}
/* setup message header with control and receive buffers */
{
msg.msg_name = 0L;
msg.msg_namelen = 0;
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
msg.msg_flags = 0;
memset(buff, 0, buff_len);
iov.iov_len = buff_len;
iov.iov_base = buff;
}
printf("Listening...\n");
/*
* main event loop
*/
while (1) {
/* prepare file descriptor sets */
{
FD_ZERO(&read_fdset);
FD_SET(s_pfk, &read_fdset);
FD_SET(s_pfk, &excp_fdset);
timeout.tv_sec = 1;
timeout.tv_usec = 0;
}
err = select(s_pfk+1, &read_fdset, NULL, &excp_fdset, &timeout);
/* error */
if (err < 0) {
fprintf(stderr, "select() error: %s.\n", strerror(errno));
}
/* select() timeout */
else if (err == 0) {
//printf(".");
}
/* socket activity */
else {
/*
* PF_KEY messages
*/
if (FD_ISSET(s_pfk, &read_fdset)) {
struct sadb_msg *pfkey_msg;
struct sadb_ext *pfkey_ext;
struct sockaddr *src, *dst;
int buffi=0;
int l;
src = dst = NULL;
err = read(s_pfk, buff, sizeof(buff));
if (err < 0) {
fprintf(stderr, "PFKEY read() error - %d %s\n", errno, strerror(errno));
}
else { /* if (err < 0) */
printf("\n");
pfkey_msg = (struct sadb_msg *)&buff[0];
switch(pfkey_msg->sadb_msg_type) {
case SADB_ACQUIRE:
printf("< SADB_ACQUIRE >\n");
break;
case SADB_GETSPI:
printf("< SADB_GETSPI >\n");
break;
case SADB_UPDATE:
printf("< SADB_UPDATE >\n");
break;
case SADB_RESERVED:
printf("< SADB_RESERVED >\n");
break;
case SADB_ADD:
printf("< SADB_ADD >\n");
break;
case SADB_DELETE:
printf("< SADB_DELETE >\n");
break;
case SADB_GET:
printf("< SADB_GET >\n");
break;
case SADB_REGISTER:
printf("< SADB_REGISTER >\n");
break;
case SADB_EXPIRE:
printf("< SADB_EXPIRE >\n");
break;
case SADB_FLUSH:
printf("< SADB_FLUSH >\n");
break;
case SADB_DUMP:
printf("< SADB_DUMP >\n");
break;
case SADB_X_PROMISC:
printf("< SADB_X_PROMISC >\n");
break;
case SADB_X_PCHANGE:
printf("< SADB_X_PCHANGE >\n");
break;
case SADB_X_SPDUPDATE:
printf("< SADB_X_SPDUPDATE >\n");
break;
case SADB_X_SPDADD:
printf("< SADB_X_SPDADD >\n");
break;
case SADB_X_SPDDELETE:
printf("< SADB_X_SPDDELETE >\n");
break;
case SADB_X_SPDGET:
printf("< SADB_X_SPDGET >\n");
break;
case SADB_X_SPDACQUIRE:
printf("< SADB_X_SPDACQUIRE >\n");
break;
case SADB_X_SPDDUMP:
printf("< SADB_X_SPDDUMP >\n");
break;
case SADB_X_SPDFLUSH:
printf("< SADB_X_SPDFLUSH >\n");
break;
case SADB_X_SPDSETIDX:
printf("< SADB_X_SPDSETIDX >\n");
break;
case SADB_X_SPDEXPIRE:
printf("< SADB_X_SPDEXPIRE >\n");
break;
case SADB_X_SPDDELETE2:
printf("< SADB_X_SPDDELETE2 >\n");
break;
case SADB_X_NAT_T_NEW_MAPPING:
printf("< SADB_X_NAT_T_NEW_MAPPING >\n");
break;
default:
printf("Got an uknown PFKEY message type (%d).\n",
pfkey_msg->sadb_msg_type);
break;
}
buffi = sizeof(struct sadb_msg);
l = 0;
printf("<base");
while(buffi < err) {
pfkey_ext = (struct sadb_ext*) &buff[buffi];
switch(pfkey_ext->sadb_ext_type) {
case SADB_EXT_RESERVED:
printf(",resrv");
break;
case SADB_EXT_SA:
l += print_sa(&obuff[l], (struct sadb_sa*)pfkey_ext);
printf(",SA");
break;
case SADB_EXT_LIFETIME_CURRENT:
printf(",lifeC");
break;
case SADB_EXT_LIFETIME_HARD:
printf(",lifeH");
break;
case SADB_EXT_LIFETIME_SOFT:
printf(",lifeS");
break;
case SADB_EXT_ADDRESS_SRC:
l += print_address(&obuff[l], (struct sadb_address*)pfkey_ext);
printf(",address_S");
break;
case SADB_EXT_ADDRESS_DST:
l += print_address(&obuff[l], (struct sadb_address*)pfkey_ext);
printf(",address_D");
break;
case SADB_EXT_ADDRESS_PROXY:
printf(",address_P");
break;
case SADB_EXT_KEY_AUTH:
printf(",key_A");
break;
case SADB_EXT_KEY_ENCRYPT:
printf(",key_E");
break;
case SADB_EXT_IDENTITY_SRC:
printf(",ident_S");
break;
case SADB_EXT_IDENTITY_DST:
printf(",ident_D");
break;
case SADB_EXT_SENSITIVITY:
printf(",sensitivity");
break;
case SADB_EXT_PROPOSAL:
printf(",proposal");
break;
case SADB_EXT_SUPPORTED_AUTH:
printf(",supported_auth");
break;
case SADB_EXT_SUPPORTED_ENCRYPT:
printf(",supported_encrypt");
break;
case SADB_EXT_SPIRANGE:
printf(",spirange");
break;
case SADB_X_EXT_KMPRIVATE:
printf(",x_kmprivate");
break;
case SADB_X_EXT_SA2:
printf(",x_SA2");
break;
case SADB_X_EXT_POLICY:
printf(",x_POLICY");
break;
case SADB_X_EXT_NAT_T_TYPE:
printf(",_X_EXT_NAT_T_TYPE");
break;
case SADB_X_EXT_NAT_T_SPORT:
printf(",x_EXT_NAT_T_SPORT");
break;
case SADB_X_EXT_NAT_T_DPORT:
printf(",x_EXT_NAT_T_DPORT");
break;
case SADB_X_EXT_NAT_T_OA:
printf(",x_EXT_NAT_T_OA");
break;
default:
printf(",(unk %d)", pfkey_ext->sadb_ext_type);
break;
} /* ebd switch */
buffi += pfkey_ext->sadb_ext_len * IPSEC_PFKEYv2_ALIGN;
} /* end while */
printf(">\n");
printf("(ver=%d ", pfkey_msg->sadb_msg_version);
printf("type=%d ", pfkey_msg->sadb_msg_type);
printf("errno=%d ", pfkey_msg->sadb_msg_errno);
printf("satype=%d ", pfkey_msg->sadb_msg_satype);
printf("len=%d ", pfkey_msg->sadb_msg_len);
printf("reserved=%d ", pfkey_msg->sadb_msg_reserved);
printf("seq=%d ", pfkey_msg->sadb_msg_seq);
printf("pid=%d)\n", pfkey_msg->sadb_msg_pid);
if (l > 0) {
l = 0;
printf("%s\n", obuff);
memset(obuff, 0, l);
}
memset(buff, 0, err);
} /* end if err */
} /* end if FDSET */
/*
* unknown (exception)
*/
else {
/* TODO: handle exceptions from excp_fdset here */
printf("unknown socket activity.");
}
}
} /* end while(1) */
return(0);
}
/*
*
* function ip_to_s()
*
* turn an unsigned 32-bit IP address into a string
* (dotted-decimal notation)
*
*/
char * ip_to_s(__u32 ip)
{
static char sIP[16];
memset(sIP, 0, sizeof(sIP));
sprintf(sIP, "%d.%d.%d.%d",
((ip >> 0)& 0xFF), ((ip >> 8)& 0xFF),
((ip >> 16)& 0xFF),((ip >> 24)& 0xFF) );
return sIP;
}
int sadb_verify(char *data, int num)
{
struct sadb_ext *ext;
ext = (struct sadb_ext*) &data[sizeof(struct sadb_msg)];
while (num) {
if (ext->sadb_ext_type == 0) break;
printf("(%d)", ext->sadb_ext_type);
ext = (struct sadb_ext *)((char *)ext + (ext->sadb_ext_len * IPSEC_PFKEYv2_ALIGN));
num--;
}
printf("\n");
return(0);
}
/*
*
* function sadb_register_old()
*
* in: s_pfk = an open PF_KEYv2 socket
* satype = type of SA to listen for
*
* out: returns success or failure
*
* sends PF_KEYv2 messages to the kernel, validates the reponse if necessary
*
*
*/
int sadb_register_old(int s_pfk, int satype)
{
static int pfk_seqno = 0;
pid_t pid = getpid();
struct sadb_msg pfkey_msgh;
struct sadb_msg *pfkey_msg;
int len, err=0;
char rbuff[20];
memset(&pfkey_msgh, 0, sizeof(struct sadb_msg));
{
/* register PF_KEY types with kernel */
/* build the PF_KEY message */
pfkey_msgh.sadb_msg_version = PF_KEY_V2;
pfkey_msgh.sadb_msg_type = SADB_REGISTER;
pfkey_msgh.sadb_msg_errno = 0;
pfkey_msgh.sadb_msg_satype = satype;
pfkey_msgh.sadb_msg_len = sizeof(struct sadb_msg) / IPSEC_PFKEYv2_ALIGN;
pfkey_msgh.sadb_msg_reserved = 0;
pfkey_msgh.sadb_msg_seq = ++pfk_seqno;
pfkey_msgh.sadb_msg_pid = pid;
len = sizeof(pfkey_msgh);
}
/* send SADB_REGISTER message to the kernel */
err = write(s_pfk, &pfkey_msgh, len);
if (err < 1){
fprintf(stderr, "pfkey write() error: %s.\n", strerror(errno));
}
/* note: select does not work here */
/* read kernel response*/
memset(rbuff, 0, sizeof(rbuff));
err = read(s_pfk, rbuff, sizeof(rbuff));
if (err < 0) {
fprintf(stderr, "PF_KEY read() error: %s.\n", strerror(errno));
return(-1);
}
/* verify response */
{
pfkey_msg = (struct sadb_msg*)rbuff;
if ((pfkey_msg->sadb_msg_version == 2) &&
(pfkey_msg->sadb_msg_type == SADB_REGISTER) &&
(pfkey_msg->sadb_msg_errno == 0) &&
(pfkey_msg->sadb_msg_satype == satype) &&
(pfkey_msg->sadb_msg_seq == pfk_seqno)){
/* TODO: if needed, insert more validation here */
/* may want to check pid */
/* may want to keep reading if seqno doesn't match */
return(err);
}
else {
fprintf(stderr, "Got invalid SADB_REGISTER back from kernel!\n");
return(-1);
}
}
return(err);
}
int print_address(char* buff, struct sadb_address* addr) {
char s[100];
int len;
char ip_string[INET6_ADDRSTRLEN];
struct sockaddr *saddr;
memset(s, 0, sizeof(s));
saddr = (struct sockaddr*)((char*)addr + sizeof(struct sadb_address));
inet_ntop(saddr->sa_family, SA2IP(saddr), ip_string, INET6_ADDRSTRLEN);
sprintf(s, "(len=%d exttype=%d proto=%d prefixlen=%d reserved=%d fam=%d addr=%s)\n",
addr->sadb_address_len,
addr->sadb_address_exttype,
addr->sadb_address_proto,
addr->sadb_address_prefixlen,
addr->sadb_address_reserved,
saddr->sa_family,
ip_string);
len = strlen(s);
memcpy(buff, s, len);
return len;
}
int print_sa(char* buff, struct sadb_sa* sa) {
char s[100];
int len;
sprintf(s, "(len=%d exttype=%d SA=%08x replay=%d state=%d auth=%d encrypt=%d flags=%d)\n",
sa->sadb_sa_len,
sa->sadb_sa_exttype,
sa->sadb_sa_spi,
sa->sadb_sa_replay,
sa->sadb_sa_state,
sa->sadb_sa_auth,
sa->sadb_sa_encrypt,
sa->sadb_sa_flags);
len = strlen(s);
memcpy(buff, s, len);
return len;
}

902
src/usermode/hip_dns.c Normal file
View File

@ -0,0 +1,902 @@
/*
* Host Identity Protocol
* Copyright (C) 2005-06 the Boeing Company
*
* 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 2 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.
*
* hip_dns.c
*
* Author: Jeff Ahrenholz <jeffrey.m.ahrenholz@boeing.com>
*
* DNS answering thread for user-mode HIP
*
*/
#ifdef __MACOSX__
#include <sys/types.h> /* __u32, etc */
#include <mac/mac_types.h>
#endif
#ifdef __WIN32__
#define _WIN32_WINNT 0x0500
#include <windows.h> /* GetComputerNameEx */
#include <win32/types.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <iphlpapi.h>
#include <io.h>
#include <time.h>
#include <WinDNS.h>
#define NS_MAXDNAME DNS_MAX_NAME_LENGTH
#define NS_PACKETSZ DNS_RFC_MAX_UDP_PACKET_LENGTH
#else
#ifdef __MACOSX__
#include <netinet/in_systm.h>
#else
#include <asm/types.h> /* __u32, etc */
#endif
#include <netinet/in.h> /* struct sockaddr_in */
#include <netinet/udp.h> /* struct sockaddr_in */
#include <arpa/inet.h> /* inet_addr() */
#include <unistd.h>
#include <pthread.h> /* phread_exit() */
#include <sys/time.h> /* gettimeofday() */
#include <arpa/nameser.h> /* NS_PACKETSZ */
#endif
#ifdef SMA_CRAWLER
#include <utime.h>
#endif
#include <stdio.h> /* printf() */
#include <string.h> /* strerror() */
#include <errno.h> /* errno */
#include <openssl/rand.h> /* RAND_bytes() */
#include <hip/hip_types.h> /* dns structures */
#include <hip/hip_funcs.h> /* dns structures */
#include <hip/hip_dns.h> /* dns structures */
#include <hip/hip_usermode.h>
#include <hip/hip_sadb.h> /* access to SADB */
/*
* Globals
*/
int dnsfd;
__u16 g_txid;
#ifdef __WIN32__
char dns_domain[255]; /* name of this machine's domain */
#endif
extern __u32 lsi_name_lookup(char *name, int namelen);
extern __u32 get_preferred_lsi(struct sockaddr *);
extern __u32 receive_hip_dns_response(unsigned char *buff, int len);
extern struct sockaddr *get_hip_dns_server();
/*
* Local function declarations
*/
int init_dns_socket();
void handle_dns_request(char *buff, int len, struct sockaddr *from);
int parse_dns_name(char *name, char *dst, int *dst_len, int *type);
int send_dns_response(char *buff, int len, struct sockaddr *to, int anstype,
char *ans);
int forward_dns_request(char *buff, int len, struct sockaddr *to);
__u16 send_hip_dns_lookup(char *name, int name_len);
__u32 get_current_dns_server();
int queue_request_info(__u16 xid, __u16 hip_request, struct sockaddr *addr);
int get_request_info(__u16 xid, __u16 hip_request, struct sockaddr *addr);
char **get_request_old_buff(__u16 xid);
/* internal data structure used to queue requests */
#define DNS_REQ_TABLE_SIZE 128
struct dns_request_info {
__u16 xid; /* DNS transaction ID */
__u16 hip_request; /* flag: 1=HIP RR lookup, 0=others */
struct sockaddr addr; /* request originator */
char *old_buff; /* for HIP RR queries, buff of non-HIP query */
};
struct dns_request_info dns_reqs[DNS_REQ_TABLE_SIZE];
/* SALEN() is not compiling correctly due to lack of IPv6 headers */
#define SALEN4(a) (sizeof struct sockaddr_in)
#define TDIFF(a, b) ((a).tv_sec - (b).tv_sec) /* Time diff in seconds */
#if 0
/* debugging code */
#define DUMP_WIDTH 16
void dns_hex_dump(char *data, int len)
{
int i, idx=0;
while (idx < (len-DUMP_WIDTH)) {
for (i=0; i < DUMP_WIDTH; i++)
printf("%2x ", data[idx + i] & 0xFF);
printf("\n");
idx += DUMP_WIDTH;
}
for (i=idx; i<len; i++)
printf("%x ", data[idx + i] & 0xFF);
printf("\n");
}
void dump_dns_hdr(struct dns_hdr *hdr)
{
if (!hdr) return;
printf("transid=%x ", hdr->transaction_id);
printf("flags=%x ", hdr->flags);
printf("qcnt=%x ", hdr->question_count);
printf("acnt=%x ", hdr->answer_count);
printf("nscnt=%x ", hdr->namesrvr_count);
printf("adcnt=%x\n", hdr->additional_count);
}
#endif
/*
* hip_dns()
*
* A simple DNS thread, intercepts DNS requests from applications and
* responds with an LSI. Forwards non-HIP DNS requests to the real DNS
* server to avoid the 2 second timeout.
*
*/
#ifdef __WIN32__
void hip_dns(void *arg)
#else
void *hip_dns(void *arg)
#endif
{
int err, len;
char buff[1024];
fd_set read_fdset;
struct timeval timeout;
struct sockaddr from;
socklen_t from_len;
#ifdef __WIN32__
DWORD dw_size;
#endif
#ifdef SMA_CRAWLER
time_t last_time, now_time;
last_time = time(NULL);
printf("hip_dns() thread (tid %d pid %d) started...\n",
(unsigned)pthread_self(), getpid());
#else
printf("hip_dns() thread started...\n");
#endif
/* initialize UDP port 53 socket */
if (!(dnsfd = init_dns_socket())) {
printf("Could not create DNS socket, aborting DNS thread.\n");
fflush(stdout);
return RETNULL
}
#ifdef __WIN32__
/* Windows optimization - get this machine's DNS domain name
* for later use
*/
dw_size = sizeof(dns_domain) - (sizeof(HIP_DNS_SUFFIX)+1);
sprintf(dns_domain, "%s.", HIP_DNS_SUFFIX);
if (!GetComputerNameEx(2,
&dns_domain[sizeof(HIP_DNS_SUFFIX)+1], &dw_size)) {
printf("Warning: couldn't get this host's DNS domain name.\n");
memset(dns_domain, 0, sizeof(dns_domain));
}
#endif /* __WIN32__ */
while(g_state == 0) {
FD_ZERO(&read_fdset);
FD_SET((unsigned)dnsfd, &read_fdset);
timeout.tv_sec = 0;
timeout.tv_usec = 500000;
#ifdef SMA_CRAWLER
now_time = time(NULL);
if (now_time - last_time > 60) {
printf("hip_dns() heartbeat\n");
last_time = now_time;
utime("/usr/local/etc/hip/heartbeat_hip_dns", NULL);
}
#endif
if ((err = select((dnsfd + 1), &read_fdset,
NULL, NULL, &timeout) < 0)) {
if (errno == EINTR)
continue;
printf("hip_dns(): select() error: %s.\n",
strerror(errno));
} else if (FD_ISSET(dnsfd, &read_fdset)) {
from_len = sizeof(struct sockaddr_in);
if ((len = recvfrom(dnsfd, buff, sizeof(buff), 0,
&from, &from_len)) < 0) {
if (errno != EINTR)
printf("DNS read error: %s\n",
strerror(errno));
continue;
}
handle_dns_request(buff, len, &from);
} /* endif select() */
}
printf("hip_dns() thread shutdown.\n");
fflush(stdout);
#ifndef __WIN32__
pthread_exit((void *) 0);
#endif
return RETNULL
}
/*
* init_dns_socket()
*/
int init_dns_socket()
{
int sockfd, retry_count=0;
struct sockaddr_in saddr;
if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
printf("Error creating DNS socket.\n");
return(-1);
}
retry_dns_bind:
memset(&saddr, 0, sizeof(struct sockaddr_in));
saddr.sin_family = AF_INET;
saddr.sin_addr.s_addr = htonl(INADDR_ANY);
if (retry_count) /* upon retry, bind specifically to the LSI */
get_preferred_lsi(SA(&saddr));
saddr.sin_port = htons(DNS_PORT);
if (bind(sockfd, (struct sockaddr *) &saddr,
sizeof(struct sockaddr_in) ) < 0) {
printf("Error binding DNS socket: (%d) %s\n", errno,
strerror(errno));
#ifdef __WIN32__
errno = WSAGetLastError();
if ((errno == WSAEADDRNOTAVAIL) && retry_count < 5) {
#else
if (((errno == EADDRNOTAVAIL) || (errno==EADDRINUSE)) &&
(retry_count < 5)) {
#endif
hip_sleep(1);
/* retry after one second */
printf("Retrying DNS bind...\n");
retry_count++;
goto retry_dns_bind;
}
#ifdef __WIN32__
closesocket(sockfd);
#else
close(sockfd);
#endif
return(0);
}
return(sockfd);
}
/*
* handle_dns_request()
*
* in: buff - buffer containing the raw DNS request
* len - length of the buffer data
* from - address of the requester
* out: none
*
* Parse the DNS request and answer those ending with .hip suffix.
* Forward normal (non .hip) requests to the real DNS server.
* Optimize for speed here.
*/
void handle_dns_request(char *buff, int len, struct sockaddr *from)
{
struct dns_hdr *dnsh = (struct dns_hdr *)buff;
struct sockaddr to;
struct sockaddr_in ntaplsi, *to4 = (struct sockaddr_in*) &to;
char namebuff[255], s_tap[16], **old_buff;
int ret, type, namelen, is_answer;
__u32 lsi, taplsi;
__u16 txid;
if (!buff || !from || len < sizeof(struct dns_hdr))
return;
is_answer = (ntohs(dnsh->flags) & DNS_FLAG_ANSWER);
ntaplsi.sin_family = AF_INET;
get_preferred_lsi(SA(&ntaplsi)); /* this call may block */
taplsi = ntohl(ntaplsi.sin_addr.s_addr);
sprintf(s_tap, "%u.%u.%u.%u", NIPQUAD(taplsi));
taplsi = ntohl(taplsi); /* recvfrom uses host order */
/* only reply to local requests */
if ( !is_answer &&
(((struct sockaddr_in *)from)->sin_addr.s_addr != taplsi))
return;
/*
* Responses from the real DNS server are matched
* with their original request and forwarded back.
*
* Responses from the HIP DNS server are matched
* with their original request, parsed/validated,
* and the LSI is returned.
*/
if (is_answer) {
if (get_request_info(dnsh->transaction_id, 0, from) < 0) {
/* check for HIP answer */
if (get_request_info(dnsh->transaction_id, 1, from) < 0)
return; /* transaction not found */
old_buff = get_request_old_buff(dnsh->transaction_id);
if (!old_buff || !*old_buff)
return; /* empty buffer */
/* parse Host Identity from response and get LSI */
lsi = receive_hip_dns_response((unsigned char *)buff, len);
namelen = sizeof(namebuff); /* read namelen, type */
parse_dns_name(*old_buff + sizeof(struct dns_hdr),
namebuff, &namelen, &type);
/* send response back */
if (lsi == 0) /* send NXDOMAIN */
send_dns_response(*old_buff, namelen, from,
DNS_TYPE_NXDOMAIN, NULL);
else /* send reply */
send_dns_response(*old_buff, namelen, from,
type, (char*)&lsi);
free(*old_buff); /* free after sendto() completed */
*old_buff = NULL;
return;
}
/* fast path */
forward_dns_request(buff, len, from);
return;
/*
* DNS queries are examined for a ".hip" suffix.
* Normal requests are forwarded to the real DNS
* server.
*/
} else if (ntohs((__u16)(dnsh->question_count > 0))) {
/*
* Does name end with .hip suffix?
*/
namelen = sizeof(namebuff);
ret = parse_dns_name((char*)(dnsh+1), namebuff, &namelen,&type);
if (ret == 1) {
/* Lookup DNS name in local peer list */
if ((lsi = lsi_name_lookup(namebuff,
namelen-4))) {
/* Name found in known_host_identities file,
* respond with LSI. */
send_dns_response(buff, namelen, from, type,
(char*)&lsi);
/* Name not found locally, look for HIP record in DNS.*/
} else {
/* We do not use res_query() here because that
* HIP request will end up back here in the DNS
* thread causing unnecessary delay.
*/
txid = send_hip_dns_lookup(namebuff, namelen-4);
if (txid == 0)
return;
/* save original request in old_buff
* we malloc(+16) so there's room to later
* append the IPv4 LSI answer
*/
queue_request_info(txid, 1, from);
old_buff = get_request_old_buff(txid);
*old_buff = malloc(len + 16);
if (!*old_buff) {
printf("hip_dns: malloc error\n");
return;
} /* XXX if we never receive a response, then
* we need to somehow free old_buff
*/
memcpy(*old_buff, buff, len);
}
return;
#ifdef __WIN32__
/* reply to .hip suffix plus domain name to eliminate
* unnecessary 2 second timeout */
} else if (ret == 2) {
send_dns_response(buff, namelen, from,
DNS_TYPE_NXDOMAIN, NULL);
return;
#endif /* __WIN32__ */
/* reply to reverse lookups of self */
} else if ((type == DNS_TYPE_PTR) &&
(strncmp(namebuff, s_tap, strlen(s_tap)) == 0)) {
send_dns_response(buff, namelen, from, type,
"localhost");
return;
} /* end if ".hip" or type==DNS_TYPE_PTR */
/* forward requests to real DNS server */
queue_request_info(dnsh->transaction_id, 0, from);
to4->sin_family = AF_INET;
to4->sin_addr.s_addr = get_current_dns_server();
to4->sin_port = htons(DNS_PORT);
/* no server available */
if (!to4->sin_addr.s_addr)
return; /* respond w/NXDOMAN? */
else
forward_dns_request(buff, len, &to);
}
}
/*
* parse_dns_name()
*
* in: name - pointer to name from question section of DNS request
* dst - pointer to string for storing parsed name
* dst_len - length of dst buffer
*
* out: dst_len - number of bytes found in string
* Returns 2 if name ends with HIP_DNS_SUFFIX + dns_domain
* Returns 1 if name ends with HIP_DNS_SUFFIX
*
* Read in a name from the DNS question section, storing it in the provided
* string and placing '.' between each section. Returns 1 if the name ends
* with the HIP_DNS_SUFFIX.
*/
int parse_dns_name(char *name, char *dst, int *dst_len, int *type)
{
char *suffix_start=NULL;
char *p, *start;
int len, total=0;
__u16 *tc;
#ifdef __WIN32__
char *first_section;
#endif /* __WIN32__ */
memset(dst, 0, *dst_len);
/* DNS name consists of a series of sections
* that begin with their section length */
len = name[0];
start = &name[1];
for (p = start; (*p != 0) && (total < *dst_len); p++) {
/* read new section length, place "." between sections */
if (len == 0) {
len = *p; /* get new length */
dst[p - start] = '.'; /* replace length with '.' */
#ifdef __WIN32__
if (!suffix_start) first_section = &dst[p - start];
#endif /* __WIN32__ */
suffix_start = &dst[p - start]; /* save last '.' */
/* copy to destination string as-is */
} else {
dst[p - &name[1]] = *p;
len--;
}
total++;
}
/* return total bytes */
*dst_len = total;
tc = (__u16*) &name[total+2];
*type = (int) ntohs(*tc);
#ifdef __WIN32__
/* check for HIP suffix with appended domain
* (i.e. host.hip.mydomain.com) - causes large speed-up for Windows
*/
len = strlen(dns_domain);
if ((first_section) && (strncmp(first_section, dns_domain, len)==0))
return(2);
#endif /* __WIN32__ */
/* check for HIP suffix */
len = sizeof(HIP_DNS_SUFFIX);
if ((suffix_start) && (strncmp(suffix_start, HIP_DNS_SUFFIX, len)==0))
return(1);
return(0);
}
/*
* build_dns_name()
*
* in: name - pointer to string containing name
* name_len - length of name
* dst - pointer for storing name in DNS format
*
* out: Returns number of bytes occupied by DNS name.
*
* Convert a string into a DNS name for inclusion in a DNS question section.
*/
int build_dns_name(char *name, int name_len, char *dst)
{
char *p, *plabel, *plabel_len;
int total=0, label_len=0;
/* DNS name consists of a series of sections
* that begin with their section length */
plabel_len = &dst[0];
plabel = &dst[1];
for (p = name; (*p != 0) && (total < name_len); p++) {
if (*p == '.') { /* go back to plabel_len and record length */
*plabel_len = label_len;
plabel_len = plabel;
plabel++;
*plabel_len = 0;
label_len = 0;
} else { /* copy string character to label */
label_len++;
*plabel = *p;
plabel++;
}
total++;
}
/* terminate with zero length label */
*plabel_len = label_len;
*plabel = '\0';
total += 2;
/* return total bytes */
return(total);
}
/*
* send_dns_response()
*
* in: buff = pointer to original request buffer
* namelen = length of domain name in question
* to = where to send the DNS reply
* anstype = type A or PTR answer?
* ans = name to answer for reverse lookups
*
* Use the dns request to generate an answer.
*/
int send_dns_response(char *buff, int namelen, struct sockaddr *to, int anstype,
char *ans)
{
struct dns_hdr *dnsh;
struct dns_ans_hdr *ansh;
char *p;
int err;
dnsh = (struct dns_hdr*)buff;
dnsh->flags |= htons(DNS_FLAG_ANSWER);
dnsh->flags |= htons(DNS_FLAG_AUTHORITATIVE);
/* answer section begins after DNS headers, plus length of
* domain name plus 4 bytes for type/class and 2 bytes for
* (start, end) name lengths */
p = (char*)(dnsh+1);
p += 6 + namelen;
if (anstype == DNS_TYPE_NXDOMAIN) {
dnsh->answer_count = 0;
dnsh->flags |= htons(DNS_FLAG_NXDOMAIN);
} else {
/* add an answer - requires more buffer space */
dnsh->answer_count = htons(1);
ansh = (struct dns_ans_hdr*) p;
ansh->ans_name = htons(0xC00C);
ansh->ans_type = htons((__u16)anstype);
ansh->ans_class = htons(DNS_QTYPE_CLASS_IN);
ansh->ans_ttl = htonl(DNS_DEFAULT_TTL); /* default 1hr */
switch (anstype) {
case DNS_TYPE_A:
ansh->ans_len = htons(sizeof(__u32));
p = (char*)(ansh+1);
memcpy(p, ans, sizeof(__u32));
p += sizeof(__u32);
break;
case DNS_TYPE_PTR:
ansh->ans_len = htons((__u16)(strlen(ans) + 2));
p = (char*)(ansh+1);
*p = strlen(ans);
p++;
p += sprintf(p, "%s", ans) + 1;
break;
default: /* unknown answer type */
return(-1);
}
}
/*
* send response back to specified address/port
*/
if ((p - buff) > NS_PACKETSZ) {
printf("send_dns_response(): name length error (len=%d)\n",
(int)(p - buff));
return(-1);
}
if ((err = sendto(dnsfd, buff, p - buff, 0, to, SALEN(to))) < 0) {
printf("send_dns_response() sendto() error: %s\n",
strerror(errno));
return(-1);
}
return(0);
}
#ifndef __CYGWIN__
#ifndef __WIN32__
#define USE_LINUX
#endif
#endif
/*
* get_current_dns_server()
*
* Windows: use GetPerAdapterInfo() to return DNS server address
* Linux: reads /etc/resolv.conf file to return DNS server address
*/
__u32 get_current_dns_server() {
#ifdef __WIN32__
static struct timeval last = {0, 0};
#else
static struct timeval last = {.tv_sec=0, .tv_usec=0};
#endif
static __u32 addr=0;
struct timeval now;
#ifdef USE_LINUX
int len;
char buff[4096], *p;
FILE *f;
memset(buff, 0, sizeof(buff));
#else
ULONG len=0, len2;
PIP_ADAPTER_INFO pAdapterInfo, pai;
PIP_PER_ADAPTER_INFO pPerAdapterInfo=NULL;
#endif
/* cache DNS server result for 5 minutes */
gettimeofday(&now, NULL);
if (TDIFF(now, last) < 300)
return(addr);
last.tv_sec = now.tv_sec;
last.tv_usec = now.tv_sec;
#ifndef USE_LINUX
GetAdaptersInfo(NULL, &len);
pAdapterInfo = (PIP_ADAPTER_INFO)malloc(len);
GetAdaptersInfo(pAdapterInfo, &len);
for (pai = pAdapterInfo; pai; pai = pai->Next) {
if (!pai->GatewayList.IpAddress.String[0])
continue;
len2 = 0;
GetPerAdapterInfo(pai->Index, NULL, &len2);
pPerAdapterInfo = (PIP_PER_ADAPTER_INFO)malloc(len2);
GetPerAdapterInfo(pai->Index, pPerAdapterInfo, &len2);
if (pPerAdapterInfo->DnsServerList.IpAddress.String[0]) {
// XXX TODO: verify that addr is in network byte order
addr = inet_addr(
pPerAdapterInfo->DnsServerList.IpAddress.String);
}
if (pPerAdapterInfo)
free(pPerAdapterInfo);
pPerAdapterInfo = NULL;
break;
}
free(pAdapterInfo);
#else
f = fopen("/etc/resolv.conf", "r");
if (!f) return(0);
while ((len = fread(buff, 1, sizeof(buff), f))) {
for (p = buff; (p = strstr(p, "nameserver ")); p += 11) {
/* position past "nameserver " (11 bytes) */
addr = inet_addr(p + 11);
if ((addr != INADDR_NONE) && (!IS_LSI32(addr)))
break;
}
}
fclose(f);
#endif
if (IS_LSI32(addr))
addr = 0;
return(addr); /* return address in network byte order */
}
/*
* forward_dns_request()
*
* Send the DNS request in buff to the specified address.
*/
int forward_dns_request(char *buff, int len, struct sockaddr *to) {
int err;
__u32 ip = ((struct sockaddr_in*)to)->sin_addr.s_addr;
/* printf("forward_dns_request() to %u.%u.%u.%u\n", NIPQUAD(ip)); */
/* check for empty address
*/
if ((to->sa_family == AF_INET) && (!ip))
return(0);
/* may want a separate forwarding socket here, if we are worried
* about overloading the use of UDP port 53.
*/
if ((err = sendto(dnsfd, buff, len, 0, to, SALEN(to))) < 0) {
printf("forward_dns_request(): sendto() error: %s\n",
strerror(errno));
return(-1);
}
return(0);
}
/*
* send_hip_dns_lookup()
*
* Request a HIP record from the DNS server. Returns the transaction ID for
* this request or zero on error.
*/
__u16 send_hip_dns_lookup(char *name, int name_len)
{
int err, len;
char buff[NS_PACKETSZ];
struct dns_hdr *dnsh;
__u16 u16;
struct sockaddr_storage to;
struct sockaddr *addr;
/* initialize DNS transaction id */
if (g_txid == 0)
RAND_bytes((unsigned char*)&g_txid, 2);
else
g_txid++;
/* DNS header */
memset(buff, 0, sizeof(buff));
dnsh = (struct dns_hdr*) buff;
dnsh->transaction_id = htons(g_txid);
dnsh->flags = htons(DNS_FLAG_MASK_STDQUERY);
dnsh->question_count = htons(1);
dnsh->answer_count = 0;
dnsh->namesrvr_count = 0;
dnsh->additional_count = 0;
len = sizeof(struct dns_hdr);
len += build_dns_name(name, name_len, &buff[len]); /* QNAME */
u16 = htons(HIP_RR_TYPE);
memcpy(&buff[len], &u16, 2); /* QTYPE */
#ifdef __WIN32__
u16 = htons(DNS_CLASS_INTERNET);
#else
u16 = htons(ns_c_in);
#endif
memcpy(&buff[len+2], &u16, 2); /* QCLASS */
len += 4;
/* send HIP DNS request to a real name server */
memset(&to, 0, sizeof(struct sockaddr_storage));
if ((addr = get_hip_dns_server())) { /* use address from hip.conf */
memcpy(&to, addr, SALEN(addr));
if (addr->sa_family == AF_INET) {
((struct sockaddr_in*)&to)->sin_port = htons(DNS_PORT);
} else {
((struct sockaddr_in6*)&to)->sin6_port =htons(DNS_PORT);
}
} else { /* use address from resolv.conf */
((struct sockaddr_in*)&to)->sin_family = AF_INET;
((struct sockaddr_in*)&to)->sin_addr.s_addr =
get_current_dns_server();
if (!((struct sockaddr_in*)&to)->sin_addr.s_addr)
return(0); /* no name server available */
((struct sockaddr_in*)&to)->sin_port = htons(DNS_PORT);
/* XXX get_current_dns_server() should
* support IPv6 from resolv.conf */
}
err = forward_dns_request(buff, len, (struct sockaddr *)&to);
if (err < 0)
return(0);
return(htons(g_txid));
}
/*
* queue_request_info()
*
* Put the return address of a DNS request into the queue.
*/
int queue_request_info(__u16 xid, __u16 hip_request, struct sockaddr *addr) {
int hash = (xid % DNS_REQ_TABLE_SIZE);
dns_reqs[hash].xid = xid;
dns_reqs[hash].hip_request = hip_request;
memcpy(&dns_reqs[hash].addr, addr, SALEN(addr));
if (dns_reqs[hash].old_buff) {
free(dns_reqs[hash].old_buff);
dns_reqs[hash].old_buff = NULL;
}
return(0);
}
/*
* get_request_info()
*
* Get the return address of a DNS request from the queue.
* Returns 0 if found, -1 if not found.
*/
int get_request_info(__u16 xid, __u16 hip_request, struct sockaddr *addr) {
int hash = (xid % DNS_REQ_TABLE_SIZE);
if (dns_reqs[hash].xid == xid) {
if (dns_reqs[hash].hip_request != hip_request)
return(-1);
memcpy(addr, &dns_reqs[hash].addr, SALEN(&dns_reqs[hash].addr));
return(0);
} else {
memset(addr, 0, sizeof(struct sockaddr));
return(-1);
}
}
/*
* get_request_old_buff()
*
* Get a pointer to the old_buff element.
*/
char **get_request_old_buff(__u16 xid) {
int hash = (xid % DNS_REQ_TABLE_SIZE);
if (dns_reqs[hash].xid == xid) {
return(&dns_reqs[hash].old_buff);
}
return NULL;
}
/*
* add_local_hip_nameserver()
*
* Set the nameserver in Linux by adding 1.x.x.x to the beginning
* of the /etc/resolv.conf file.
*/
void add_local_hip_nameserver(__u32 ip)
{
size_t len;
FILE *f;
char buff[4096], tapstr[32]; /* buff holds all of resolv.conf */
memset(buff, 0, sizeof(buff));
memset(tapstr, 0, sizeof(tapstr));
f = fopen("/etc/resolv.conf", "r+");
if (!f) return;
sprintf(tapstr, "nameserver %u.%u.%u.%u\n", NIPQUAD(ip));
len = fread(buff, sizeof(char), sizeof(buff), f);
if (len && (strstr(buff, tapstr))) { /* does 1.x.x.x already exist? */
fclose(f);
return;
}
rewind(f);
if (fwrite(tapstr, sizeof(char), strlen(tapstr), f) != strlen(tapstr))
printf("Warning: unable to write HIP DNS entry to "
"/etc/resolv.conf\n");
if (fwrite(buff, sizeof(char), len, f) != len)
printf("Warning: unable to preserve %d bytes of data in "
"/etc/resolv.conf\n", (int)len);
fclose(f);
}
/*
* delete_local_hip_nameserver()
*
* Remove 1.x.x.x from the /etc/resolv.conf file.
*/
void delete_local_hip_nameserver(__u32 ip)
{
size_t len;
FILE *f;
char buff[4096], tapstr[32]; /* buff holds all of resolv.conf */
memset(buff, 0, sizeof(buff));
memset(tapstr, 0, sizeof(tapstr));
f = fopen("/etc/resolv.conf", "r+");
if (!f) return;
sprintf(tapstr, "nameserver %u.%u.%u.%u\n", NIPQUAD(ip));
len = fread(buff, sizeof(char), sizeof(buff), f);
fclose(f);
/* if 1.x.x.x LSI already exists, rewrite the file without it */
if (len && (strstr(buff, tapstr))) {
f = fopen("/etc/resolv.conf", "w");
len -= strlen(tapstr);
if (fwrite(&buff[strlen(tapstr)], sizeof(char), len, f) != len)
printf("Warning: unable to remove HIP DNS entry from "
"/etc/resolv.conf\n");
fclose(f);
}
}

2675
src/usermode/hip_esp.c Normal file

File diff suppressed because it is too large Load Diff

891
src/usermode/hip_mr.c Normal file
View File

@ -0,0 +1,891 @@
/*
* Host Identity Protocol
* Copyright (C) 2005-08 the Boeing Company
*
* 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 2 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.
*
* hip_mr.c
*
* Authors: Jeff Ahrenholz <jeffrey.m.ahrenholz@boeing.com>
* Orlie Brewer <orlie.t.brewer@boeing.com>
*
* Mobile router SPINAT implemenation
*
*/
#ifdef __WIN32__
#include <win32/types.h>
#include <winsock2.h>
#include <iphlpapi.h>
#include <io.h>
#else
#include <unistd.h>
#include <pthread.h> /* phread_exit() */
#include <netinet/ip.h> /* struct ip */
#include <netinet/ip6.h> /* struct ip6_hdr */
#include <netinet/icmp6.h> /* struct icmp6_hdr */
#include <netinet/tcp.h> /* struct tcphdr */
#include <netinet/udp.h> /* struct udphdr */
#include <arpa/inet.h>
#include <linux/netfilter.h>
#include <libipq.h>
#endif /* WIN32 */
#include <stdio.h> /* printf() */
#include <string.h> /* strerror() */
#include <errno.h> /* errno */
#include <hip/hip_service.h>
#include <hip/hip_types.h>
#include <hip/hip_funcs.h>
#include <hip/hip_globals.h>
#include <openssl/rand.h> /* RAND_bytes() */
#define INET6_ADDRSTRLEN 46
#define BUFSIZE 2048
struct ip_esp_hdr {
__u32 spi;
__u32 seq_no;
__u8 enc_data[0];
};
extern hip_mr_client hip_mr_client_table[MAX_MR_CLIENTS];
extern int max_hip_mr_clients;
extern int external_if_index;
extern int new_external_address;
extern pthread_mutex_t hip_mr_client_mutex;
static struct sockaddr_storage out_addr;
struct spi_table {
__u32 private_spi;
__u32 public_spi;
hip_hit mn_hit;
hip_hit peer_hit;
struct sockaddr_storage mn_addr;
struct sockaddr_storage peer_addr;
struct spi_table *next;
};
int hip_send_proxy_update(struct sockaddr *newaddr, struct sockaddr *dstaddr,
hip_hit *mn_hit, hip_hit *peer_hit,
hip_proxy_ticket *ticket, __u32 spi);
int build_tlv_proxy_hmac(hip_proxy_ticket *ticket, __u8 *data, int location,
int type);
/*
*
* function get_next_spinat()
*
* in: none
*
* out: returns next SPI value to use for SPINAT
*
* Obtains new random SPI for SPINAT, checks that it is not being used.
* TODO: Should also check that it is not being used for mobile router SAs.
*/
__u32 get_next_spinat(void)
{
int i;
__u32 new_spi;
hip_spi_nat *spi_nats;
retry_getspi:
/* randomly select a new SPI */
new_spi = 0;
while (new_spi <= SPI_RESERVED) {
RAND_bytes((__u8*)&new_spi, 4);
}
for (i = 0; i < max_hip_mr_clients; i++) {
for (spi_nats = hip_mr_client_table[i].spi_nats; spi_nats;
spi_nats = spi_nats->next) {
if (new_spi == spi_nats->public_spi)
goto retry_getspi;
}
}
return new_spi;
}
hip_mr_client *check_hits(hip_hit the_hit)
{
int i;
for (i = 0; i < max_hip_mr_clients; i++) {
if (hits_equal(the_hit, hip_mr_client_table[i].mn_hit)) {
struct sockaddr *src = (struct sockaddr*)&hip_mr_client_table[i].mn_addr;
printf("This is for Mobile Router client %s\n", logaddr(src));
return &hip_mr_client_table[i];
}
}
return NULL;
}
void adjust_addrs(struct sockaddr_storage *s, struct sockaddr_storage *d,
struct ip6_hdr *ip6h)
{
struct sockaddr *src, *dst;
src = (struct sockaddr *)s;
dst = (struct sockaddr *)d;
src->sa_family = AF_INET6;
dst->sa_family = AF_INET6;
memcpy(&ip6h->ip6_src, SA2IP(src), sizeof(struct in6_addr));
memcpy(&ip6h->ip6_dst, SA2IP(dst), sizeof(struct in6_addr));
}
void process_I1(hip_mr_client *hip_mr_c, hiphdr *hiph,
struct ip6_hdr *ip6h)
{
struct sockaddr *dst;
hip_spi_nat *spi_nats = hip_mr_c->spi_nats;
while (spi_nats) {
if (hits_equal(hiph->hit_rcvr, spi_nats->peer_hit)) {
break;
}
spi_nats = spi_nats->next;
}
if (!spi_nats) {
spi_nats = malloc(sizeof(hip_spi_nat));
if (!spi_nats)
return;
memset(spi_nats, 0, sizeof(hip_spi_nat));
spi_nats->next = hip_mr_c->spi_nats;
hip_mr_c->spi_nats = spi_nats;
memcpy(spi_nats->peer_hit, hiph->hit_rcvr, sizeof(hip_hit));
}
spi_nats->private_spi = 0;
spi_nats->public_spi = 0;
dst = (struct sockaddr *)&spi_nats->peer_addr;
dst->sa_family = AF_INET6;
memcpy(SA2IP(dst), &ip6h->ip6_dst, SAIPLEN(dst));
adjust_addrs(&out_addr, &spi_nats->peer_addr, ip6h);
return;
}
void process_R1(hip_mr_client *hip_mr_c, hiphdr *hiph,
struct ip6_hdr *ip6h)
{
hip_spi_nat *spi_nats = hip_mr_c->spi_nats;
while (spi_nats) {
if (hits_equal(hiph->hit_sndr, spi_nats->peer_hit)) {
break;
}
spi_nats = spi_nats->next;
}
if (!spi_nats)
return;
adjust_addrs(&spi_nats->peer_addr, &hip_mr_c->mn_addr, ip6h);
}
__u32 process_I2(hip_mr_client *hip_mr_c, hiphdr *hiph,
struct ip6_hdr *ip6h)
{
int location = 0;
__u8 *data = (__u8 *)hiph;
int data_len;
int type, length;
tlv_head *tlv;
tlv_esp_info *esp_info;
hip_spi_nat *spi_nats = hip_mr_c->spi_nats;
while (spi_nats) {
if (hits_equal(hiph->hit_rcvr, spi_nats->peer_hit)) {
break;
}
spi_nats = spi_nats->next;
}
if (!spi_nats)
return 0;
data_len = (hiph->hdr_len+1) * 8;
location += sizeof(hiphdr);
while (location < data_len) {
tlv = (tlv_head *) &data[location];
type = ntohs(tlv->type);
length = ntohs(tlv->length);
if (type == PARAM_ESP_INFO) {
esp_info = (tlv_esp_info *)tlv;
spi_nats->private_spi = ntohl(esp_info->new_spi);
spi_nats->public_spi = get_next_spinat();
printf("Private SPI 0x%x added\n", spi_nats->private_spi);
printf("Public SPI 0x%x added\n", spi_nats->public_spi);
break;
}
location += tlv_length_to_parameter_length(length);
}
adjust_addrs(&out_addr, &spi_nats->peer_addr, ip6h);
return spi_nats->public_spi;
}
void process_R2(hip_mr_client *hip_mr_c, hiphdr *hiph,
struct ip6_hdr *ip6h)
{
int location = 0;
__u8 *data = (__u8 *)hiph;
int data_len;
int type, length;
tlv_head *tlv;
tlv_esp_info *esp_info;
hip_spi_nat *spi_nats = hip_mr_c->spi_nats;
while (spi_nats) {
if (hits_equal(hiph->hit_sndr, spi_nats->peer_hit)) {
break;
}
spi_nats = spi_nats->next;
}
if (!spi_nats)
return;
data_len = (hiph->hdr_len+1) * 8;
location += sizeof(hiphdr);
while (location < data_len) {
tlv = (tlv_head *) &data[location];
type = ntohs(tlv->type);
length = ntohs(tlv->length);
if (type == PARAM_ESP_INFO) {
esp_info = (tlv_esp_info *)tlv;
spi_nats->peer_spi = ntohl(esp_info->new_spi);
printf("Peer SPI 0x%x added\n", spi_nats->peer_spi);
break;
}
location += tlv_length_to_parameter_length(length);
}
adjust_addrs(&spi_nats->peer_addr, &hip_mr_c->mn_addr, ip6h);
}
void process_CLOSE(hip_mr_client *hip_mr_c, hiphdr *hiph,
struct ip6_hdr *ip6h, int packet_type)
{
int in_bound;
hip_hit *peer_hit;
hip_spi_nat *spi_nats = hip_mr_c->spi_nats;
if (hits_equal(hiph->hit_sndr, hip_mr_c->mn_hit)) {
in_bound = 0;
peer_hit = &(hiph->hit_rcvr);
} else {
in_bound = 1;
peer_hit = &(hiph->hit_sndr);
}
while (spi_nats) {
if (hits_equal(*peer_hit, spi_nats->peer_hit)) {
break;
}
spi_nats = spi_nats->next;
}
if (!spi_nats)
return;
if (in_bound) {
adjust_addrs(&spi_nats->peer_addr, &hip_mr_c->mn_addr, ip6h);
} else {
adjust_addrs(&out_addr, &spi_nats->peer_addr, ip6h);
}
/* Remove state for SA */
if (packet_type == CLOSE_ACK) {
;
}
}
unsigned char *add_tlv_spi_nat(unsigned char *payload, size_t data_len,
size_t *new_len, __u32 new_spi)
{
struct ip6_hdr *ip6h = (struct ip6_hdr*)payload;
hiphdr *hiph = (hiphdr *)(payload + sizeof(struct ip6_hdr));
tlv_esp_info *esp_info;
size_t len = data_len + sizeof(tlv_esp_info);
int hiphdr_len;
unsigned char *buff = malloc(len);
if (!buff) {
return buff;
}
memcpy(buff, payload, data_len);
ip6h = (struct ip6_hdr*)buff;
hiph = (hiphdr *)(buff + sizeof(struct ip6_hdr));
hiphdr_len = (hiph->hdr_len+1) * 8;
/* ESP INFO */
esp_info = (tlv_esp_info*) &buff[data_len];
esp_info->type = htons(PARAM_ESP_INFO_NOSIG);
esp_info->length = htons(sizeof(tlv_esp_info) - 4);
esp_info->reserved = 0;
esp_info->keymat_index = 0;
esp_info->old_spi = 0;
esp_info->new_spi = htonl(new_spi);
/* finish with new length */
hiphdr_len += sizeof(tlv_esp_info);
ip6h->ip6_plen = htons((unsigned short)hiphdr_len);
hiph->hdr_len = (hiphdr_len/8) - 1;
printf("Adding SPI_NAT of 0x%x\n", new_spi);
*new_len = len;
return buff;
}
void generate_hip_updates(struct sockaddr *out)
{
int i;
for (i = 0; i < max_hip_mr_clients; i++) {
if (RESPONSE_SENT == hip_mr_client_table[i].state) {
hip_spi_nat *spi_nats;
struct sockaddr *src = (struct sockaddr*)&hip_mr_client_table[i].mn_addr;
printf("Doing UPDATE for Mobile Router client %s\n", logaddr(src));
for (spi_nats = hip_mr_client_table[i].spi_nats;
spi_nats; spi_nats = spi_nats->next) {
struct sockaddr *dst =
(struct sockaddr*)&spi_nats->peer_addr;
hip_send_proxy_update(out, dst,
&hip_mr_client_table[i].mn_hit,
&spi_nats->peer_hit,
&spi_nats->ticket,
spi_nats->public_spi);
}
}
}
}
void check_address_change(void)
{
sockaddr_list *l;
struct sockaddr *out = (struct sockaddr *)&out_addr;
if (!new_external_address)
return;
for (l = my_addr_head; l; l=l->next) {
if (l->if_index == external_if_index &&
l->addr.ss_family == AF_INET6) {
struct in6_addr ip6_addr, ip6_old_addr;
memcpy(&ip6_addr, SA2IP((struct sockaddr *)&l->addr),
sizeof(struct in6_addr));
if (!IN6_IS_ADDR_LINKLOCAL(&ip6_addr) &&
!IN6_IS_ADDR_LOOPBACK(&ip6_addr) &&
!IN6_IS_ADDR_SITELOCAL(&ip6_addr)) {
memcpy(&ip6_old_addr, SA2IP(out),
sizeof(struct in6_addr));
if (IN6_ARE_ADDR_EQUAL(&ip6_addr,
&ip6_old_addr))
return;
out->sa_family = AF_INET6;
memcpy(SA2IP(out),
SA2IP((struct sockaddr *)&l->addr),
SAIPLEN(out));
pthread_mutex_lock(&hip_mr_client_mutex);
new_external_address = FALSE;
printf("Need to generate UPDATE packet for new address %s\n", logaddr(out));
generate_hip_updates(out);
pthread_mutex_unlock(&hip_mr_client_mutex);
break;
}
}
}
}
unsigned char *check_hip_packet(unsigned char *payload, size_t data_len,
size_t *new_len)
{
struct sockaddr *src, *dst;
struct sockaddr_storage src_addr, dst_addr;
struct ip6_hdr *ip6h = (struct ip6_hdr*)payload;
hiphdr *hiph = (hiphdr *)(payload + sizeof(struct ip6_hdr));
hip_mr_client *hip_mr_c;
int length = (hiph->hdr_len+1) * 8;
unsigned char *buff = NULL;
switch(hiph->packet_type) {
case HIP_I1:
pthread_mutex_lock(&hip_mr_client_mutex);
hip_mr_c = check_hits(hiph->hit_sndr);
if (hip_mr_c) {
process_I1(hip_mr_c, hiph, ip6h);
}
pthread_mutex_unlock(&hip_mr_client_mutex);
printf("HIP I1 packet of length %d\n", length);
break;
case HIP_R1:
pthread_mutex_lock(&hip_mr_client_mutex);
hip_mr_c = check_hits(hiph->hit_rcvr);
if (hip_mr_c) {
process_R1(hip_mr_c, hiph, ip6h);
}
pthread_mutex_unlock(&hip_mr_client_mutex);
printf("HIP R1 packet of length %d\n", length);
break;
case HIP_I2:
pthread_mutex_lock(&hip_mr_client_mutex);
hip_mr_c = check_hits(hiph->hit_sndr);
if (hip_mr_c) {
__u32 new_spi;
new_spi = process_I2(hip_mr_c, hiph, ip6h);
if (new_spi) {
buff = add_tlv_spi_nat(payload,
data_len, new_len, new_spi);
}
}
pthread_mutex_unlock(&hip_mr_client_mutex);
printf("HIP I2 packet of length %d\n", length);
break;
case HIP_R2:
pthread_mutex_lock(&hip_mr_client_mutex);
hip_mr_c = check_hits(hiph->hit_rcvr);
if (hip_mr_c) {
process_R2(hip_mr_c, hiph, ip6h);
}
pthread_mutex_unlock(&hip_mr_client_mutex);
printf("HIP R2 packet of length %d\n", length);
break;
case CLOSE:
case CLOSE_ACK:
pthread_mutex_lock(&hip_mr_client_mutex);
if ((hip_mr_c = check_hits(hiph->hit_rcvr)) ||
(hip_mr_c = check_hits(hiph->hit_sndr))) {
process_CLOSE(hip_mr_c, hiph, ip6h,
hiph->packet_type);
}
pthread_mutex_unlock(&hip_mr_client_mutex);
if (hiph->packet_type == CLOSE)
printf("HIP CLOSE ");
else
printf("HIP CLOSE ACK ");
printf("packet of length %d\n", length);
break;
}
/* finish with new checksum */
if (buff) {
ip6h = (struct ip6_hdr*)buff;
hiph = (hiphdr *)(buff + sizeof(struct ip6_hdr));
}
src = (struct sockaddr *)&src_addr;
src->sa_family = AF_INET6;
dst = (struct sockaddr *)&dst_addr;
dst->sa_family = AF_INET6;
memcpy(SA2IP(src), &(ip6h->ip6_src), SAIPLEN(src));
memcpy(SA2IP(dst), &(ip6h->ip6_dst), SAIPLEN(dst));
hiph->checksum = 0;
hiph->checksum = checksum_packet((__u8 *)hiph, src, dst);
printf(" from HIT ");
print_hex(hiph->hit_sndr, HIT_SIZE);
printf(" to HIT ");
print_hex(hiph->hit_rcvr, HIT_SIZE);
printf("\n");
return buff;
}
void check_esp_packet(struct ip6_hdr *ip6h, struct ip_esp_hdr *esph)
{
int i, inbound = 0;
struct sockaddr *out, *addr;
struct in6_addr ip6_dst, ip6_src;
printf("ESP packet with SPI 0x%x\n", ntohl(esph->spi));
out = (struct sockaddr *)&out_addr;
out->sa_family = AF_INET6;
memcpy(&ip6_dst, SA2IP(out), sizeof(struct in6_addr));
if (IN6_ARE_ADDR_EQUAL(&ip6h->ip6_dst, &ip6_dst)) {
inbound = 1;
}
pthread_mutex_lock(&hip_mr_client_mutex);
for (i = 0; i < max_hip_mr_clients; i++) {
addr = (struct sockaddr *)&hip_mr_client_table[i].mn_addr;
addr->sa_family = AF_INET6;
memcpy(&ip6_src, SA2IP(addr), sizeof(struct in6_addr));
hip_spi_nat *spi_nats = hip_mr_client_table[i].spi_nats;
while (spi_nats) {
if (inbound &&
(spi_nats->public_spi == ntohl(esph->spi))) {
printf("Found the public SPI 0x%x\n", ntohl(esph->spi));
printf("Changing to 0x%x\n", spi_nats->private_spi);
esph->spi = htonl(spi_nats->private_spi);
adjust_addrs(&spi_nats->peer_addr,
&hip_mr_client_table[i].mn_addr,
ip6h);
pthread_mutex_unlock(&hip_mr_client_mutex);
return;
} else if (!inbound &&
(spi_nats->peer_spi == ntohl(esph->spi)) &&
IN6_ARE_ADDR_EQUAL(&ip6h->ip6_src, &ip6_src)) {
adjust_addrs(&out_addr, &spi_nats->peer_addr,
ip6h);
}
spi_nats = spi_nats->next;
}
}
pthread_mutex_unlock(&hip_mr_client_mutex);
}
#ifdef __WIN32__
void hip_mobile_router(void *arg)
#else
void *hip_mobile_router(void *arg)
#endif
{
int status, type;
unsigned char buf[BUFSIZE];
unsigned char *new_buff;
size_t new_len;
struct ipq_handle *h;
struct ip6_hdr *ip6h;
struct ip_esp_hdr *esph;
ipq_packet_msg_t *m;
char buffer[INET6_ADDRSTRLEN];
sockaddr_list *l;
struct sockaddr *out = (struct sockaddr *)&out_addr;
printf("hip_mobile_router() thread started...\n");
/* TODO: get from interface name spec in config file to interface index
Also, for an address/interface UPDATE change, how to get that info
to this thread?
external_if_index = devname_to_index("eth0", NULL);
*/
for (l = my_addr_head; l; l=l->next) {
if (l->if_index == external_if_index &&
l->addr.ss_family == AF_INET6) {
struct in6_addr ip6_addr;
memcpy(&ip6_addr, SA2IP((struct sockaddr *)&l->addr),
sizeof(struct in6_addr));
if (!IN6_IS_ADDR_LINKLOCAL(&ip6_addr) &&
!IN6_IS_ADDR_LOOPBACK(&ip6_addr) &&
!IN6_IS_ADDR_SITELOCAL(&ip6_addr)) {
out->sa_family = AF_INET6;
memcpy(SA2IP(out),
SA2IP((struct sockaddr *)&l->addr),
SAIPLEN(out));
break;
}
}
}
/*
struct in6_addr ip6_out;
out = (struct sockaddr *)&out_addr;
out->sa_family = AF_INET6;
inet_pton(AF_INET6, "2002:822a:20ec:1::3", &ip6_out);
memcpy(SA2IP(out), &ip6_out, SAIPLEN(out));
*/
h = ipq_create_handle(0, PF_INET6);
if (!h) {
printf("hip_mobile_router() - ipq_create_handle() "
"failed: %s\n", ipq_errstr());
fflush(stdout);
#ifdef __WIN32__
return;
#else
return NULL;
#endif
}
status = ipq_set_mode(h, IPQ_COPY_PACKET, BUFSIZE);
if (status < 0) {
printf("hip_mobile_router() - ipq_set_mode() failed: %s\n",
ipq_errstr());
ipq_destroy_handle(h);
fflush(stdout);
#ifdef __WIN32__
return;
#else
return NULL;
#endif
}
while(g_state == 0) {
check_address_change();
status = ipq_read(h, buf, BUFSIZE, 5);
if (status < 0) {
printf("hip_mobile_router() - ipq_read() failed: %s\n",
ipq_errstr());
continue;
} else if (status == 0) { /* Timed out */
continue;
}
type = ipq_message_type(buf);
if (NLMSG_ERROR == type) {
printf("Received error message %d\n",
ipq_get_msgerr(buf));
continue;
} else if (IPQM_PACKET != type) {
printf("Received unexpected type %d\n", type);
continue;
}
m = ipq_get_packet(buf);
new_buff = m->payload;
new_len = m->data_len;
ip6h = (struct ip6_hdr*)m->payload;
printf("\nPacket from %s",
inet_ntop(AF_INET6, &(ip6h->ip6_src),
buffer, sizeof(buffer)));
printf(" to %s\n",
inet_ntop(AF_INET6, &(ip6h->ip6_dst),
buffer, sizeof(buffer)));
if (m->indev_name[0] != 0 && m->outdev_name[0] == 0)
printf(" INPUT from %s\n\n", m->indev_name);
else if (m->indev_name[0] != 0 && m->outdev_name[0] != 0)
printf(" FORWARD from %s to %s\n\n", m->indev_name,
m->outdev_name);
else if (m->indev_name[0] == 0 && m->outdev_name[0] != 0)
printf(" OUTPUT to %s\n\n", m->outdev_name);
if (ip6h->ip6_nxt == H_PROTO_HIP) {
unsigned char *temp_buff;
size_t len;
temp_buff = check_hip_packet(m->payload, m->data_len,
&len);
if (temp_buff) {
new_buff = temp_buff;
new_len = len;
}
} else if (ip6h->ip6_nxt == IPPROTO_ESP) {
esph = (struct ip_esp_hdr *)
(m->payload + sizeof(struct ip6_hdr));
check_esp_packet(ip6h, esph);
}
status = ipq_set_verdict(h, m->packet_id, NF_ACCEPT,
new_len, new_buff);
if (status < 0) {
printf("hip_mobile_router() - ipq_set_verdict() "
"failed: %s\n", ipq_errstr());
continue;
}
}
printf("hip_mobile_router() thread shutdown.\n");
ipq_destroy_handle(h);
fflush(stdout);
#ifndef __WIN32__
pthread_exit((void *) 0);
return(NULL);
#endif
}
/*
*
* function hip_send_update()
*
* in: hip_a = HIP association containing valid source/destination
* addresses, HITs, SPIs, key material, pub key
* newaddr = new preferred address to include in LOCATOR, or NULL
* dstaddr = alternate destination address, if this is an address
* check message, otherwise NULL
*
* out: Returns bytes sent when successful, -1 on error.
*
* Opens a socket and sends the UPDATE packet.
* Packet will be scheduled for retransmission if it contains a SEQ (that
* needs to be ACKed.)
*
*/
int hip_send_proxy_update(struct sockaddr *newaddr, struct sockaddr *dstaddr,
hip_hit *mn_hit, hip_hit *peer_hit,
hip_proxy_ticket *ticket, __u32 spi_in)
{
struct sockaddr *src, *dst;
hiphdr *hiph;
__u8 buff[sizeof(hiphdr) + 2*sizeof(tlv_locator) +
sizeof(tlv_auth_ticket) +
sizeof(tlv_hmac) + sizeof(tlv_hip_sig) +
MAX_SIG_SIZE + 2 ];
int location=0, retransmit=FALSE;
tlv_locator *loc;
tlv_auth_ticket *auth_ticket;
locator *loc1;
__u32 loc_spi;
memset(buff, 0, sizeof(buff));
src = newaddr;
dst = dstaddr;
/* build the HIP header */
hiph = (hiphdr*) buff;
hiph->nxt_hdr = IPPROTO_NONE;
hiph->hdr_len = 0;
hiph->packet_type = UPDATE;
hiph->version = HIP_PROTO_VER;
hiph->res = HIP_RES_SHIM6_BITS;
hiph->control = 0;
hiph->checksum = 0;
memcpy(&hiph->hit_sndr, mn_hit, sizeof(hip_hit));
memcpy(&hiph->hit_rcvr, peer_hit, sizeof(hip_hit));
location = sizeof(hiphdr);
/* set control bits */
hiph->control = htons(hiph->control);
/*
* Add LOCATOR parameter when supplied with readdressing info.
*/
if (newaddr) {
loc = (tlv_locator*) &buff[location];
loc->type = htons(PARAM_LOCATOR);
loc->length = htons(sizeof(tlv_locator) - 4);
loc1 = &loc->locator1[0];
loc1->traffic_type = LOCATOR_TRAFFIC_TYPE_BOTH;
loc1->locator_type = LOCATOR_TYPE_SPI_IPV6;
loc1->locator_length = 5; /* (32 + 128 bits) / 4 */
loc1->reserved = LOCATOR_PREFERRED; /* set the P-bit */
loc1->locator_lifetime = htonl(HCNF.loc_lifetime);
memset(loc1->locator, 0, sizeof(loc1->locator));
loc_spi = htonl(spi_in);
memcpy(loc1->locator, &loc_spi, 4);
if (newaddr->sa_family == AF_INET6) {
memcpy(&loc1->locator[4], SA2IP(newaddr),
SAIPLEN(newaddr));
} else {/* IPv4-in-IPv6 address format */
memset(&loc1->locator[14], 0xFF, 2);
memcpy(&loc1->locator[16], SA2IP(newaddr),
SAIPLEN(newaddr));
}
location += sizeof(tlv_locator);
location = eight_byte_align(location);
add_reg_request = FALSE;
}
/* AUTH_TICKET */
auth_ticket = (tlv_auth_ticket *) &buff[location];
auth_ticket->type = htons(PARAM_AUTH_TICKET);
auth_ticket->length = htons(sizeof(tlv_auth_ticket) - 4);
auth_ticket->hmac_key_index = htons(ticket->hmac_key_index);
auth_ticket->transform_type = htons(ticket->transform_type);
auth_ticket->action = htons(ticket->action);
auth_ticket->lifetime = htons(ticket->lifetime);
memcpy(auth_ticket->hmac, ticket->hmac, sizeof(auth_ticket->hmac));
location += sizeof(tlv_auth_ticket);
location = eight_byte_align(location);
/* HMAC */
hiph->hdr_len = (location/8) - 1;
location += build_tlv_proxy_hmac(ticket, buff, location, PARAM_HMAC);
#ifdef NOT
/* HIP signature */
hiph->hdr_len = (location/8) - 1;
location += build_tlv_signature(hip_a->hi, buff, location, FALSE);
#endif
hiph->hdr_len = (location/8) - 1;
hiph->checksum = 0;
hiph->checksum = checksum_packet(buff, src, dst);
/* send the packet */
log_(NORMT, "sending UPDATE packet (%d bytes)...\n", location);
/* Retransmit UPDATEs unless it contains a LOCATOR or address check */
log_(NORM, "Sending UPDATE packet to dst : %s \n", logaddr(dst));
/*
hip_check_bind(src, use_udp, HIP_UPDATE_BIND_CHECKS);
*/
return(hip_send(buff, location, src, dst, NULL, retransmit, 0, 0));
}
int build_tlv_proxy_hmac(hip_proxy_ticket *ticket, __u8 *data, int location,
int type)
{
hiphdr *hiph;
tlv_hmac *hmac;
unsigned int hmac_md_len;
unsigned char hmac_md[EVP_MAX_MD_SIZE];
/* compute HMAC over message */
hiph = (hiphdr*) data;
memset(hmac_md, 0, sizeof(hmac_md));
hmac_md_len = EVP_MAX_MD_SIZE;
switch (ticket->transform_type) {
case ESP_AES_CBC_HMAC_SHA1:
case ESP_3DES_CBC_HMAC_SHA1:
case ESP_BLOWFISH_CBC_HMAC_SHA1:
case ESP_NULL_HMAC_SHA1:
HMAC( EVP_sha1(),
ticket->hmac_key,
auth_key_len(ticket->transform_type),
data, location,
hmac_md, &hmac_md_len );
break;
case ESP_3DES_CBC_HMAC_MD5:
case ESP_NULL_HMAC_MD5:
HMAC( EVP_md5(),
ticket->hmac_key,
auth_key_len(ticket->transform_type),
data, location,
hmac_md, &hmac_md_len );
break;
default:
return(0);
break;
}
log_(NORM, "HMAC computed over %d bytes hdr length=%d\n ",
location, hiph->hdr_len);
/* build tlv header */
hmac = (tlv_hmac*) &data[location];
hmac->type = htons((__u16)type);
hmac->length = htons(sizeof(tlv_hmac) - 4);
/* get lower 160-bits of HMAC computation */
memcpy( hmac->hmac,
&hmac_md[hmac_md_len-sizeof(hmac->hmac)],
sizeof(hmac->hmac));
return(eight_byte_align(sizeof(tlv_hmac)));
}

428
src/usermode/hip_nl.c Normal file
View File

@ -0,0 +1,428 @@
/*
* Host Identity Protocol
* Copyright (C) 2005-06 the Boeing Company
*
* 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 2 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.
*
* hip_nl.c
*
* Authors: Jeff Ahrenholz <jeffrey.m.ahrenholz@boeing.com>
*
* User-mode minimal Netlink sockets layer
*
*/
#ifdef __WIN32__
#include <win32/types.h>
#include <winsock2.h>
#include <iphlpapi.h>
#include <io.h>
#else
#include <windows.h>
#include <w32api/iphlpapi.h>
#include <unistd.h>
#include <pthread.h> /* phread_exit() */
#endif
#include <stdio.h> /* printf() */
#include <string.h> /* strerror() */
#include <errno.h> /* errno */
#include <hip/hip_service.h>
#include <hip/hip_types.h>
#include <hip/hip_sadb.h> /* access to SADB */
#include <win32/rtnetlink.h> /* from <linux/rtnetlink.h> */
/*
* Globals
*/
int netlsp[2];
extern __u32 g_tap_lsi;
/*
* Local function declarations
*/
void readIpAddrTable(PMIB_IPADDRTABLE *pTable);
int checkIpAddrTableChanges(PMIB_IPADDRTABLE pNew, PMIB_IPADDRTABLE pOld);
int netlink_send_addr(int add_del, DWORD addr, DWORD ifindex);
int sendIpAddrTable(PMIB_IPADDRTABLE pTable);
/*
* hip_netlink()
*
* A simple rtnetlink socket emulation layer, acts as the kernel side
* of netlink sockets, for providing address updates to the HIP daemon.
*
*/
#ifdef __WIN32__
void hip_netlink(void *arg)
#else
void *hip_netlink(void *arg)
#endif
{
int err;
char buff[1024];
PMIB_IPADDRTABLE pTable, pTableOld;
fd_set read_fdset;
struct timeval timeout;
/* note that this would be cleaner with the libiphlpapi.a function:
ret = NotifyAddrChange(&hand, &overlap);
which is not currently supported by Cygwin/mingw
*/
printf("hip_netlink() thread started...\n");
if (socketpair(AF_UNIX, SOCK_DGRAM, PF_UNIX, netlsp)) {
printf("hip_netlink() - socketpair() failed: %s\n",
strerror(errno));
fflush(stdout);
#ifdef __WIN32__
return;
#else
return NULL;
#endif
}
pTable = NULL;
pTableOld = NULL;
while(g_state == 0) {
readIpAddrTable(&pTable);
if (!pTableOld) { /* first loop, set pTableOld */
pTableOld = pTable;
pTable = NULL;
}
if (checkIpAddrTableChanges(pTable, pTableOld)) {
/* save newly-changed table */
free(pTableOld);
pTableOld = pTable;
pTable = NULL;
}
FD_ZERO(&read_fdset);
FD_SET((unsigned)netlsp[0], &read_fdset);
#ifdef __WIN32__
Sleep(500);
#else
timeout.tv_sec = 0;
timeout.tv_usec = 500000; /* refresh every 0.5 seconds */
select(0, NULL, NULL, NULL, &timeout);
#endif
timeout.tv_sec = 0;
timeout.tv_usec = 0;
if ((err = select((netlsp[0] + 1), &read_fdset,
NULL, NULL, &timeout) < 0)) {
if (errno == EINTR)
continue;
printf("hip_netlink(): select() error: %s.\n",
strerror(errno));
//} else if (err == 0) {
} else if (FD_ISSET(netlsp[0], &read_fdset)) {
#ifdef __WIN32__
if ((err = recv(netlsp[0], buff, sizeof(buff), 0)) < 0){
#else
if ((err = read(netlsp[0], buff, sizeof(buff))) < 0) {
#endif
if (errno == EINTR)
continue;
printf("Netlink read error: %s\n",
strerror(errno));
continue;
}
if (((struct nlmsghdr*)buff)->nlmsg_type==RTM_GETADDR) {
/* send dump of IP address table */
sendIpAddrTable(pTableOld);
} else {
printf("Received unknown netlink message");
printf("type %d, ignoring.\n",
((struct nlmsghdr*)buff)->nlmsg_type);
}
}
}
printf("hip_netlink() thread shutdown.\n");
fflush(stdout);
#ifndef __WIN32__
pthread_exit((void *) 0);
return(NULL);
#endif
}
void readIpAddrTable(PMIB_IPADDRTABLE *pTable)
{
DWORD size = 0, ret;
if (*pTable == NULL) {
*pTable = (MIB_IPADDRTABLE*) malloc(sizeof(MIB_IPADDRTABLE));
}
if (GetIpAddrTable(*pTable, &size, 0) ==
ERROR_INSUFFICIENT_BUFFER) {
free(*pTable);
*pTable = (MIB_IPADDRTABLE*) malloc(size);
}
if ((ret = GetIpAddrTable(*pTable, &size, 0)) == NO_ERROR) {
}
}
//typedef struct _MIB_IPADDRTABLE {
// DWORD dwNumEntries;
// MIB_IPADDRROW table[ANY_SIZE];
//} MIB_IPADDRTABLE,
// *PMIB_IPADDRTABLE;
//typedef struct _MIB_IPADDRROW {
// DWORD dwAddr; // IP Address
// DWORDIF_INDEX dwIndex; // Interface index
// DWORD dwMask;
// DWORD dwBCastAddr;
// DWORD dwReasmSize;
// unsigned short unused1;
// unsigned short wType; // IP address type/state
// } MIB_IPADDRROW,
// *PMIB_IPADDRROW;
//
#define MIB_IPADDR_PRIMARY 0x0001 /* Primary IP address */
#define MIB_IPADDR_DYNAMIC 0x0004 /* Dynamic IP address */
#define MIB_IPADDR_DISCONNECTED 0x0008 /* Address is on disconnected iface */
#define MIB_IPADDR_DELETED 0x0040 /* Address is being deleted */
#define MIB_IPADDR_TRANSIENT 0x0080 /* Transient Address */
int checkIpAddrTableChanges(PMIB_IPADDRTABLE pNew, PMIB_IPADDRTABLE pOld)
{
enum {
IP_ADD,
IP_DEL,
IP_CHG,
};
int i, max, ret=0;
if (!pNew || !pOld)
return(0);
max = (pNew->dwNumEntries > pOld->dwNumEntries) ? pNew->dwNumEntries:
pOld->dwNumEntries;
//printf("IP table: [");
for (i = 0; i < max; i++) {
//printf("%u.%u.%u.%u(%d) ", NIPQUAD(pNew->table[i].dwAddr),
// (int)pNew->table[i].dwIndex);
#ifdef __WIN32__
if ((pNew->table[i].dwAddr != pOld->table[i].dwAddr) ||
(pNew->table[i].wType != pOld->table[i].wType)) {
if ((pNew->table[i].wType & MIB_IPADDR_DELETED) ||
((pNew->table[i].wType & MIB_IPADDR_DISCONNECTED)))
netlink_send_addr(1, pOld->table[i].dwAddr,
pOld->table[i].dwIndex);
#else
if ((pNew->table[i].dwAddr != pOld->table[i].dwAddr) ||
(pNew->table[i].unused2 != pOld->table[i].unused2)) {
/* unused2 is wType */
/* Address deleted due to flags */
if ((pNew->table[i].unused2 & MIB_IPADDR_DELETED) ||
((pNew->table[i].unused2 & MIB_IPADDR_DISCONNECTED)))
netlink_send_addr(1, pOld->table[i].dwAddr,
pOld->table[i].dwIndex);
#endif
/* Address deleted, replaced by 0.0.0.0 */
else if ((pNew->table[i].dwAddr == 0) &&
(pOld->table[i].dwAddr) &&
(pOld->table[i].dwIndex ==
pNew->table[i].dwIndex))
netlink_send_addr(1, pOld->table[i].dwAddr,
pOld->table[i].dwIndex);
/* New address */
else {
/* first delete old address, if any */
if ((pOld->table[i].dwAddr) &&
(pOld->table[i].dwIndex ==
pNew->table[i].dwIndex))
netlink_send_addr(1,
pOld->table[i].dwAddr,
pOld->table[i].dwIndex);
/* send new address */
netlink_send_addr(0, pNew->table[i].dwAddr,
pNew->table[i].dwIndex);
}
ret = 1;
}
}
//printf("]\n");
return ret;
}
/*
* 0 = add, 1 = deleted
*/
int netlink_send_addr(int add_del, DWORD addr, DWORD ifindex)
{
char buff[512];
int len;
struct nlmsghdr *msg;
struct ifaddrmsg *ifa;
struct rtattr *rta;
__u32 *p_addr;
/* ignore 0.0.0.0 and 1.x.x.x */
if ((addr == 0) || (addr == g_tap_lsi))
return(0);
/* printf("Address %u.%u.%u.%u has been ", NIPQUAD(addr));
printf("%s.\n", add_del ? "deleted" : "added"); */
/* netlink message header */
memset(buff, 0, sizeof(buff));
msg = (struct nlmsghdr*) &buff[0];
len = NLMSG_LENGTH( sizeof(struct ifaddrmsg) + sizeof(struct rtattr) +
sizeof(__u32));
msg->nlmsg_len = NLMSG_ALIGN(len);
msg->nlmsg_type = add_del ? RTM_DELADDR : RTM_NEWADDR;
msg->nlmsg_flags = 0;
msg->nlmsg_seq = 0;
msg->nlmsg_pid = 0;
/* interface address message */
ifa = (struct ifaddrmsg*) NLMSG_DATA(msg);
ifa->ifa_family = AF_INET;
ifa->ifa_prefixlen = 32;
ifa->ifa_flags = IFA_F_PERMANENT;
ifa->ifa_scope = IFA_LOCAL;
ifa->ifa_index = ifindex;
/* route attributes */
rta = IFA_RTA(ifa);
rta->rta_len = RTA_LENGTH(sizeof(__u32));
rta->rta_type = IFA_LOCAL;
p_addr = (__u32*)(rta+1);
*p_addr = addr; /* host byte order */
#ifdef __WIN32__
if (send(netlsp[0], buff, len, 0) < 0) {
#else
if (write(netlsp[0], buff, len) < 0) {
#endif
printf("netlink_send_addr() write error: %s", strerror(errno));
return(-1);
}
return(0);
}
#ifdef ADAPTER_INFO
PIP_ADAPTER_INFO pAdapterInfo;
PIP_ADAPTER_INFO a = NULL;
ULONG outBufLen;
DWORD ret;
pAdapterInfo = (IP_ADAPTER_INFO*) malloc( sizeof(IP_ADAPTER_INFO) );
outBufLen = sizeof(IP_ADAPTER_INFO);
/* Determine size of buffer */
if (GetAdaptersInfo(pAdapterInfo, &outBufLen) == ERROR_BUFFER_OVERFLOW){
free(pAdapterInfo);
pAdapterInfo = (IP_ADAPTER_INFO*) malloc(outBufLen);
}
/* */
if ((ret = GetAdaptersInfo( pAdapterInfo, &outBufLen)) == NO_ERROR) {
for (a = pAdapterInfo; a; a = a->Next ) {
printf("Adapter: %s ", a->AdapterName);
printf("IP: %s\n", a->IpAddressList.IpAddress.String);
}
} else {
printf("Error reading adapter info.\n");
}
free(pAdapterInfo);
#endif
int sendIpAddrTable(PMIB_IPADDRTABLE pTable)
{
char buff[1024];
int len, total_len=0, status, i;
struct nlmsghdr *msg;
struct ifaddrmsg *ifa;
struct rtattr *rta;
__u32 *p_addr;
if (!pTable)
return(-1);
memset(buff, 0, sizeof(buff));
status = sizeof(buff);
len = NLMSG_LENGTH( sizeof(struct ifaddrmsg) + sizeof(struct rtattr) +
sizeof(__u32));
msg = (struct nlmsghdr *) buff;
/* due to timing, 1.0.0.1 is not in Window's IP table yet,
* but is needed by hipd for the ACQUIRE, so here we add
* it manually */
msg->nlmsg_len = NLMSG_ALIGN(len);
total_len += len;
msg->nlmsg_type = NLMSG_NOOP;
msg->nlmsg_flags = 0;
msg->nlmsg_seq = 0;
msg->nlmsg_pid = 0;
ifa = (struct ifaddrmsg*) NLMSG_DATA(msg);
ifa->ifa_family = AF_INET;
ifa->ifa_prefixlen = 32;
ifa->ifa_flags = IFA_F_PERMANENT;
ifa->ifa_scope = IFA_LOCAL;
ifa->ifa_index = 65542;
rta = IFA_RTA(ifa);
rta->rta_len = RTA_LENGTH(sizeof(__u32));
rta->rta_type = IFA_LOCAL;
p_addr = (__u32*)(rta+1);
*p_addr = g_tap_lsi;
msg = NLMSG_NEXT(msg, status);
/* step through IP address table and add to netlink dump message */
for(i = 0; i < (int)pTable->dwNumEntries; i++) {
/* omit 0.0.0.0; (1.0.0.1 is needed for ACQUIRE mechanism) */
if (pTable->table[i].dwAddr == 0)
continue;
msg->nlmsg_len = NLMSG_ALIGN(len);
total_len += len;
msg->nlmsg_type = NLMSG_NOOP;
msg->nlmsg_flags = 0;
msg->nlmsg_seq = 0;
msg->nlmsg_pid = 0;
/* interface address message */
ifa = (struct ifaddrmsg*) NLMSG_DATA(msg);
ifa->ifa_family = AF_INET;
ifa->ifa_prefixlen = 32;
ifa->ifa_flags = IFA_F_PERMANENT;
ifa->ifa_scope = IFA_LOCAL;
ifa->ifa_index = pTable->table[i].dwIndex;
/* route attributes */
rta = IFA_RTA(ifa);
rta->rta_len = RTA_LENGTH(sizeof(__u32));
rta->rta_type = IFA_LOCAL;
p_addr = (__u32*)(rta+1);
*p_addr = pTable->table[i].dwAddr;
msg = NLMSG_NEXT(msg, status);
}
/* finish with a done message */
msg->nlmsg_len = NLMSG_LENGTH(0);
msg->nlmsg_type = NLMSG_DONE;
msg->nlmsg_flags = 0;
msg->nlmsg_seq = 0;
msg->nlmsg_pid = 0;
total_len += msg->nlmsg_len;
#ifdef __WIN32__
send(netlsp[0], buff, total_len, 0);
#else
write(netlsp[0], buff, total_len);
#endif
return(total_len);
}

834
src/usermode/hip_pfkey.c Normal file
View File

@ -0,0 +1,834 @@
/*
* Host Identity Protocol
* Copyright (C) 2004-06 the Boeing Company
*
* 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 2 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.
*
* hip_pfkey.c
*
* Authors: Jeff Ahrenholz <jeffrey.m.ahrenholz@boeing.com>
*
* User-mode minimal PFKEYv2 implementation.
*
*/
#include <stdio.h> /* printf() */
#ifdef __WIN32__
#include <winsock2.h>
#include <ws2tcpip.h>
#include <io.h>
#include <win32/types.h>
#else
#include <unistd.h>
#include <pthread.h> /* phread_exit() */
#endif
#include <string.h> /* strerror() */
#include <errno.h> /* errno */
#include <hip/hip_types.h>
#include <hip/hip_service.h>
#include <hip/hip_sadb.h> /* access to SADB */
#include <win32/pfkeyv2.h>
#ifdef SMA_CRAWLER
#include <utime.h>
#endif
/*
* Globals
*/
int pfkeysp[2];
static int pfk_seqno=0;
#define PFKEY_UNIT64(a) ((a) >> 3)
#define PFKEY_ALIGN8(a) (1 + (((a) - 1) | (8 - 1)))
/*
* Local function declarations
*/
#ifdef __WIN32__
void hip_pfkey(void *arg);
#else
void *hip_pfkey(void *arg);
#endif
int pfkey_handle_getspi(int sock, char *data, int len);
int pfkey_handle_add(int sock, char *data, int len);
int pfkey_handle_delete(int sock, char *data, int len);
int pfkey_handle_register(int sock, char *data, int len);
int pfkey_handle_get(int sock, char *data, int len);
int pfkey_handle_spdadd(int sock, char *data, int len);
int pfkey_handle_spddelete(int sock, char *data, int len);
int pfkey_handle_readdress(int sock, char *data, int len);
int pfkey_handle_acquire(char *data, int len);
int pfkey_send_acquire(struct sockaddr *target);
extern int get_preferred_lsi(struct sockaddr *lsi);
/*
* hip_pfkey()
*
* The PFKEYv2 listener thread, that handles PF_KEY_V2 messages
* in lieu of the Linux kernel.
*/
#ifdef __WIN32__
void hip_pfkey(void *arg)
#else
void *hip_pfkey(void *arg)
#endif
{
int len, err;
fd_set fd;
struct timeval timeout;
char buff[1024];
struct sadb_msg *msg;
#ifdef SMA_CRAWLER
time_t last_time, now_time;
last_time = time(NULL);
printf("hip_pfkey() thread (tid %d pid %d) started...\n",
(unsigned)pthread_self(), getpid());
#else
printf("hip_pfkey() thread started...\n");
#endif
#ifdef __MACOSX__
if (socketpair(AF_UNIX, SOCK_DGRAM, PF_UNSPEC, pfkeysp)) {
#else
if (socketpair(AF_UNIX, SOCK_DGRAM, PF_UNIX, pfkeysp)) {
#endif
printf("hip_pfkey() - socketpair() failed: %s\n",
strerror(errno));
fflush(stdout);
#ifdef __WIN32__
return;
#else
return NULL;
#endif
}
while(g_state == 0) {
/* periodic select loop */
FD_ZERO(&fd);
FD_SET((unsigned)pfkeysp[0], &fd);
#ifdef __MACOSX__
timeout.tv_sec = 1;
timeout.tv_usec = 0;
#else
timeout.tv_sec = 0;
timeout.tv_usec = 1000000;
#endif
#ifdef SMA_CRAWLER
now_time = time(NULL);
if (now_time - last_time > 60) {
printf("hip_pfkey() heartbeat\n");
last_time = now_time;
utime("/usr/local/etc/hip/heartbeat_hip_pfkey", NULL);
}
#endif
if ((err = select(pfkeysp[0]+1, &fd, NULL, NULL, &timeout))< 0){
if (errno == EINTR)
continue;
printf("hip_pfkey(): select() error\n");
} else if (err == 0) {
/* idle cycle */
continue;
}
/* pfkey data on socket */
#ifdef __WIN32__
if ((len = recv(pfkeysp[0], buff, sizeof(buff), 0)) < 0) {
if (errno == EINTR)
continue;
printf("hip_pfkey(): read() failed\n");
fflush(stdout);
return;
}
#else
if ((len = read(pfkeysp[0], buff, sizeof(buff))) < 0) {
if (errno == EINTR)
continue;
printf("hip_pfkey(): read() failed\n");
return NULL;
}
#endif
msg = (struct sadb_msg*) buff;
if (msg->sadb_msg_version != PF_KEY_V2)
continue;
switch (msg->sadb_msg_type) {
case SADB_GETSPI:
pfkey_handle_getspi(pfkeysp[0], buff, len);
break;
case SADB_ADD:
pfkey_handle_add(pfkeysp[0], buff, len);
break;
case SADB_DELETE:
pfkey_handle_delete(pfkeysp[0], buff, len);
break;
case SADB_GET:
pfkey_handle_get(pfkeysp[0], buff, len);
break;
case SADB_REGISTER:
pfkey_handle_register(pfkeysp[0], buff, len);
break;
case SADB_X_SPDADD:
pfkey_handle_spdadd(pfkeysp[0], buff, len);
break;
case SADB_X_SPDDELETE:
pfkey_handle_spddelete(pfkeysp[0], buff, len);
break;
case SADB_READDRESS:
pfkey_handle_readdress(pfkeysp[0], buff, len);
break;
case SADB_HIP_ACQUIRE:
if (pfkey_handle_acquire(buff, len) < 0)
printf("*** pfkey: Error with HIP acquire -- " \
" ESP problems likely.\n");
break;
default:
break;
}
}
printf("hip_pfkey() thread shutdown.\n");
fflush(stdout);
#ifndef __WIN32__
pthread_exit((void *) 0);
return(NULL);
#endif
}
/*
* pfkey_handle_getspi()
*
* Expects a spirange with min == max, check if SPI is already in use.
* Note that this differs from RFC 2367 in that no LARVAL security association
* is generated, so do not follow this with a SADB_DELETE message.
*/
int pfkey_handle_getspi(int sock, char *data, int len)
{
int msg_length, location, ext_len;
struct sadb_msg *msg;
struct sadb_ext *ext;
struct sadb_spirange *spirange;
__u32 spi = 0;
msg = (struct sadb_msg*) data;
msg_length = msg->sadb_msg_len * sizeof(__u64);
location = sizeof(struct sadb_msg);
while (location < msg_length) {
ext = (struct sadb_ext*) &data[location];
ext_len = ext->sadb_ext_len * sizeof(__u64);
switch (ext->sadb_ext_type) {
case SADB_EXT_SPIRANGE:
spirange = (struct sadb_spirange*) ext;
spi = spirange->sadb_spirange_min;
break;
default:
break;
}
location += ext_len;
}
if (!spi) {
msg->sadb_msg_errno = -1;
} else if (hip_sadb_lookup_spi(spi)) {
msg->sadb_msg_errno = -EEXIST;
} else {
msg->sadb_msg_errno = 0;
}
#ifdef __WIN32__
send(sock, data, len, 0);
#else
if (write(sock, data, len) != len)
return(-1);
#endif
return(0);
}
/*
* pfkey_handle_add()
*
* Adds an SA to the SADB.
*/
int pfkey_handle_add(int sock, char *data, int len)
{
__u32 type, spi, e_type, e_keylen, a_type, a_keylen, lifetime;
int err, location, msg_length, ext_len;
struct sockaddr *src, *dst;
struct sockaddr *inner_src, *inner_dst;
__u32 mode;
__u16 dst_port;
__u8 *a_key, *e_key;
__u16 hitmagic;
int is_src=0, addr_len=0;
struct sadb_msg *msg;
struct sadb_ext *ext;
struct sadb_sa *sa;
struct sadb_lifetime *life;
struct sadb_address *addr;
struct sadb_key *key;
struct sadb_ident *ident;
struct sadb_x_sa2 *x_sa2;
struct sadb_x_nat_t_port *natt_port;
type = spi = 0;
e_type = e_keylen = 0;
a_type = a_keylen = 0;
lifetime = 0;
hitmagic = 0;
src = dst = NULL;
inner_src = inner_dst = NULL;
mode = 0;
dst_port = 0;
a_key = e_key = NULL;
msg = (struct sadb_msg*) data;
/* <base, SA, (lifetime(HS),) address(SD), (address(P),),
key(AE), (identity(SD),), (sensitivity)> */
msg_length = msg->sadb_msg_len * sizeof(__u64);
location = sizeof(struct sadb_msg);
while (location < msg_length) {
ext = (struct sadb_ext*) &data[location];
ext_len = ext->sadb_ext_len * sizeof(__u64);
switch (ext->sadb_ext_type) {
case SADB_EXT_SA:
sa = (struct sadb_sa*) ext;
spi = ntohl(sa->sadb_sa_spi);
a_type = sa->sadb_sa_auth;
e_type = sa->sadb_sa_encrypt;
break;
case SADB_EXT_LIFETIME_HARD:
life = (struct sadb_lifetime*) ext;
lifetime = (__u32)life->sadb_lifetime_addtime;
break;
case SADB_EXT_LIFETIME_CURRENT:
case SADB_EXT_LIFETIME_SOFT:
break;
case SADB_EXT_ADDRESS_SRC:
is_src = 1;
case SADB_EXT_ADDRESS_DST:
addr = (struct sadb_address*) ext;
addr_len = addr->sadb_address_prefixlen;
addr++;
if (is_src) src = (struct sockaddr*)addr;
else dst = (struct sockaddr*)addr;
is_src = 0;
break;
case SADB_EXT_IDENTITY_SRC:
is_src = 1;
case SADB_EXT_IDENTITY_DST:
ident = (struct sadb_ident*) ext;
addr_len = ident->sadb_ident_len;
ident++;
if (is_src) inner_src = (struct sockaddr*)ident;
else inner_dst = (struct sockaddr*)ident;
is_src = 0;
break;
case SADB_X_EXT_SA2:
x_sa2 = (struct sadb_x_sa2*) ext;
mode = (__u32) x_sa2->sadb_x_sa2_mode;
break;
case SADB_X_EXT_NAT_T_DPORT:
natt_port = (struct sadb_x_nat_t_port*) ext;
dst_port = ntohs (natt_port->sadb_x_nat_t_port_port);
break;
case SADB_X_EXT_NAT_T_SPORT:
natt_port = (struct sadb_x_nat_t_port*) ext;
/* src_port is ignored */
break;
case SADB_EXT_KEY_AUTH:
key = (struct sadb_key*) ext;
a_keylen = key->sadb_key_bits/8;
if (a_keylen == 0)
goto add_error;
key++;
a_key = (__u8*)key;
break;
case SADB_EXT_KEY_ENCRYPT:
key = (struct sadb_key*) ext;
e_keylen = key->sadb_key_bits/8;
key++;
e_key = (__u8*)key;
break;
case SADB_EXT_HIT:
hitmagic = ((struct sadb_hit*)ext)->sadb_hit;
break;
default:
printf("Warning: unknown TLV in PF_KEY message.\n ");
goto add_error;
break;
}
location += ext_len;
}
err = hip_sadb_add(type, mode, inner_src, inner_dst, src,
dst, dst_port, spi, e_key, e_type, e_keylen,
a_key, a_type, a_keylen, lifetime, hitmagic,
msg->sadb_msg_pid);
if (err < 0)
msg->sadb_msg_errno = err;
goto addsend;
add_error:
msg->sadb_msg_errno = -1;
addsend:
#ifdef __WIN32__
send(sock, data, len, 0);
#else
if (write(sock, data, len) != len)
return(-1);
#endif
return(0);
}
/*
* pfkey_handle_delete()
*
* Deletes an SA from the SADB.
*/
int pfkey_handle_delete(int sock, char *data, int len)
{
__u32 type, spi;
int err, location, msg_length, ext_len;
struct sockaddr *src, *dst;
int is_src=0, addr_len=0;
struct sadb_msg *msg;
struct sadb_ext *ext;
struct sadb_sa *sa;
struct sadb_address *addr;
type = spi = 0;
src = dst = NULL;
msg = (struct sadb_msg*) data;
msg_length = msg->sadb_msg_len * sizeof(__u64);
location = sizeof(struct sadb_msg);
while (location < msg_length) {
ext = (struct sadb_ext*) &data[location];
ext_len = ext->sadb_ext_len * sizeof(__u64);
switch (ext->sadb_ext_type) {
case SADB_EXT_SA:
sa = (struct sadb_sa*) ext;
spi = ntohl(sa->sadb_sa_spi);
break;
case SADB_EXT_ADDRESS_SRC:
is_src = 1;
case SADB_EXT_ADDRESS_DST:
addr = (struct sadb_address*) ext;
addr_len = addr->sadb_address_prefixlen;
addr++;
if (is_src) src = (struct sockaddr*)addr;
else dst = (struct sockaddr*)addr;
is_src = 0;
break;
default:
break;
}
location += ext_len;
}
err = hip_sadb_delete(type, src, dst, spi);
if (err < 0)
msg->sadb_msg_errno = err;
#ifdef __WIN32__
send(sock, data, len, 0);
#else
if (write(sock, data, len) != len)
return(-1);
#endif
return(0);
}
/*
* pfkey_handle_get()
*
* Only the SPI is used from the SADB_GET to lookup the SA.
* Reply with SADB_DUMP containing bytes used and usetime.
* Note that, unlike RFC 2367, this does not dump everything.
*/
int pfkey_handle_get(int sock, char *data, int len)
{
char buff[255];
__u32 spi;
int err, location, msg_length, ext_len;
struct sockaddr *src, *dst;
int is_src=0, addr_len=0;
__u64 bytes, usetime;
struct sadb_msg *msg, *reply_msg;
struct sadb_ext *ext;
struct sadb_sa *sa;
struct sadb_address *addr;
struct sadb_lifetime *life;
hip_sadb_entry *entry;
spi = 0;
src = dst = NULL;
bytes = 0;
usetime = 0;
err = 0;
msg = (struct sadb_msg*) data;
msg_length = msg->sadb_msg_len * sizeof(__u64);
location = sizeof(struct sadb_msg);
while (location < msg_length) {
ext = (struct sadb_ext*) &data[location];
ext_len = ext->sadb_ext_len * sizeof(__u64);
switch (ext->sadb_ext_type) {
case SADB_EXT_SA:
sa = (struct sadb_sa*) ext;
spi = ntohl(sa->sadb_sa_spi);
break;
case SADB_EXT_ADDRESS_SRC:
is_src = 1;
case SADB_EXT_ADDRESS_DST:
addr = (struct sadb_address*) ext;
addr_len = addr->sadb_address_prefixlen;
addr++;
if (is_src) src = (struct sockaddr*)addr;
else dst = (struct sockaddr*)addr;
is_src = 0;
break;
default:
break;
}
location += ext_len;
}
/* src, dst are ignored */
/* get the bytes used from the SADB entry */
if ((entry = hip_sadb_lookup_spi(spi))) {
bytes = entry->bytes;
usetime = entry->usetime.tv_sec;
} else {
err = -1;
}
/* build the SADB_DUMP reply */
memset(buff, 0, sizeof(buff));
msg_length = sizeof(struct sadb_msg) + sizeof(struct sadb_lifetime);
reply_msg = (struct sadb_msg*)buff;
reply_msg->sadb_msg_version = PF_KEY_V2;
reply_msg->sadb_msg_type = SADB_DUMP;
reply_msg->sadb_msg_errno = err;
reply_msg->sadb_msg_satype = msg->sadb_msg_satype;
reply_msg->sadb_msg_len = msg_length / sizeof(__u64);
reply_msg->sadb_msg_reserved = 0;
reply_msg->sadb_msg_seq = msg->sadb_msg_seq;
reply_msg->sadb_msg_pid = 0;
life = (struct sadb_lifetime*)&buff[sizeof(struct sadb_msg)];
life->sadb_lifetime_len = sizeof(struct sadb_lifetime) / sizeof(__u64);
life->sadb_lifetime_exttype = SADB_EXT_LIFETIME_CURRENT;
life->sadb_lifetime_allocations = 0;
life->sadb_lifetime_bytes = bytes;
life->sadb_lifetime_addtime = 0;
life->sadb_lifetime_usetime = usetime;
#ifdef __WIN32__
send(sock, buff, msg_length, 0);
#else
if (write(sock, buff, msg_length) != msg_length)
return(-1);
#endif
return(0);
}
/*
* pfkey_handle_register()
*
* This is a no-op, since we're using a socketpair, only one process
* can "register" communication with us. Echo back the SADB_REGISTER message.
*/
int pfkey_handle_register(int sock, char *data, int len)
{
struct sadb_msg *msg;
msg = (struct sadb_msg*) data;
msg->sadb_msg_errno = 0;
msg->sadb_msg_pid = 0;
#ifdef __WIN32__
send(sock, data, len, 0);
#else
if (write(sock, data, len) != len)
return(-1);
#endif
return(0);
}
/*
* pfkey_handle_spdadd()
*
* Another no-op function. No SPD is used.
* However, direction of the SA is established based on this SPDADD input.
*/
int pfkey_handle_spdadd(int sock, char *data, int len)
{
int location, msg_length, ext_len;
struct sockaddr *src, *dst;
int is_src=0, addr_len=0;
__u8 direction;
struct sadb_msg *msg;
struct sadb_ext *ext;
struct sadb_address *addr;
struct sadb_x_policy *policy;
hip_sadb_entry *entry;
src = dst = NULL;
direction = 0;
msg = (struct sadb_msg*) data;
msg_length = msg->sadb_msg_len * sizeof(__u64);
location = sizeof(struct sadb_msg);
while (location < msg_length) {
ext = (struct sadb_ext*) &data[location];
ext_len = ext->sadb_ext_len * sizeof(__u64);
if (ext_len == 0) {
dst = NULL; /* error */
break;
}
switch (ext->sadb_ext_type) {
case SADB_EXT_ADDRESS_SRC:
is_src = 1;
case SADB_EXT_ADDRESS_DST:
addr = (struct sadb_address*) ext;
addr_len = addr->sadb_address_prefixlen;
addr++;
if (is_src) src = (struct sockaddr*)addr;
else dst = (struct sockaddr*)addr;
is_src = 0;
break;
case SADB_X_EXT_POLICY:
/* direction: 2 == outgoing, 1 == incoming*/
policy = (struct sadb_x_policy*) ext;
direction = policy->sadb_x_policy_dir;
default:
break;
}
location += ext_len;
}
/* get the bytes used from the SADB entry */
if (dst && (entry = hip_sadb_lookup_addr(dst))) {
entry->direction = direction;
msg->sadb_msg_errno = 0;
} else {
printf("Warning: SA not found using address in "
"pfkey_handle_spadd(). dst=%p\n", dst);
msg->sadb_msg_errno = -1;
}
#ifdef __WIN32__
send(sock, data, len, 0);
#else
if (write(sock, data, len) != len)
return(-1);
#endif
return(0);
}
/*
* pfkey_handle_spddelete()
*
* Another no-op function. No SPD is used.
*/
int pfkey_handle_spddelete(int sock, char *data, int len)
{
struct sadb_msg *msg;
msg = (struct sadb_msg*) data;
msg->sadb_msg_errno = 0;
msg->sadb_msg_pid = 0;
#ifdef __WIN32__
send(sock, data, len, 0);
#else
if (write(sock, data, len) != len)
return(-1);
#endif
return(0);
}
/*
* pfkey_handle_readdress()
*
* Currently, another no-op function. See comment below.
*/
int pfkey_handle_readdress(int sock, char *data, int len)
{
struct sadb_msg *msg;
msg = (struct sadb_msg*) data;
/* TODO:
* perform any action here?
* In the Linux kernel, we must walk the established sockets
* list, but that is not necessary due to LSI usage here.
*
* Currently, the LSI mapping is updated via an extra
* modified ACQUIRE message sent to pfkey, and that
* could be moved here.
*/
#ifdef __WIN32__
send(sock, data, len, 0);
#else
if (write(sock, data, len) != len)
return(-1);
#endif
return(0);
}
/*
* pfkey_handle_acquire()
*
* Handle special ACQUIRE messages that come from the HIP daemon for updating
* the LSI -> IP address mapping. This was done so that we could learn about
* LSIs here without having to further modify libipsec.
*/
int pfkey_handle_acquire(char *data, int len)
{
struct sadb_msg *msg;
struct sadb_address *addr;
struct sockaddr_storage ss_src, ss_lsi4, ss_lsi6;
struct sockaddr *src = (struct sockaddr*)&ss_src;
struct sockaddr *lsi4 = (struct sockaddr*)&ss_lsi4;
struct sockaddr *lsi6 = (struct sockaddr*)&ss_lsi6;
int location, addr_len;
msg = (struct sadb_msg*) data;
/* retrieve the new IP address */
location = sizeof(struct sadb_msg);
addr = (struct sadb_address*) &data[location];
if (addr->sadb_address_exttype != SADB_EXT_ADDRESS_SRC)
return(-1);
addr_len = addr->sadb_address_len * sizeof(__u64);
memcpy(src, addr+1, addr_len - sizeof(struct sadb_address));
location += addr_len;
/* retrieve the IPv4 LSI */
addr = (struct sadb_address*) &data[location];
if (addr->sadb_address_exttype != SADB_EXT_ADDRESS_DST)
return(-1);
addr_len = addr->sadb_address_len * sizeof(__u64);
memcpy(lsi4, addr+1, addr_len - sizeof(struct sadb_address));
location += addr_len;
if (lsi4->sa_family == AF_INET)
LSI4(lsi4) = ntohl(LSI4(lsi4));
/* retrieve the IPv6 LSI */
addr = (struct sadb_address*) &data[location];
if (addr->sadb_address_exttype != SADB_EXT_ADDRESS_DST)
return(-1);
addr_len = addr->sadb_address_len * sizeof(__u64);
memcpy(lsi6, addr+1, addr_len - sizeof(struct sadb_address));
hip_add_lsi(src, lsi4, lsi6);
return(0);
}
/*
* pfkey_send_acquire()
*
* Sends a SADB_HIP_ACQUIRE message to the HIP daemon for triggering
* a HIP exchange.
*/
int pfkey_send_acquire(struct sockaddr *target)
{
char buff[256];
struct sadb_msg *msg = (struct sadb_msg*) buff;
struct sadb_address *addr;
struct sadb_prop *proposal;
struct sockaddr_storage ss_local;
struct sockaddr *local = (struct sockaddr *)&ss_local;
int len, extlen, plen, location;
if (!target)
return(-1);
/* <base, address(SD), (address(P)), (identity(SD),) (sensitivity,)
proposal> */
len = sizeof(struct sadb_msg) + (2*sizeof(struct sadb_address)) +
(2*PFKEY_ALIGN8(SALEN(target))) + sizeof(struct sadb_prop);
memset(buff, 0, len);
msg->sadb_msg_version = PF_KEY_V2;
msg->sadb_msg_type = SADB_HIP_ACQUIRE;
msg->sadb_msg_errno = 0;
msg->sadb_msg_satype = SADB_SATYPE_ESP;
msg->sadb_msg_len = PFKEY_UNIT64(len);
msg->sadb_msg_reserved = 0;
msg->sadb_msg_seq = ++pfk_seqno;
msg->sadb_msg_pid = 0;
memset(local, 0, sizeof(struct sockaddr_storage));
switch (target->sa_family) {
case AF_INET:
plen = sizeof(struct in_addr) << 3;
local->sa_family = AF_INET;
get_preferred_lsi(local);
LSI4(target) = htonl(LSI4(target));
break;
case AF_INET6:
plen = sizeof(struct in6_addr) << 3;
local->sa_family = AF_INET6;
get_preferred_lsi(local);
break;
default:
return(-1);
}
location = sizeof(struct sadb_msg);
addr = (struct sadb_address*)&buff[location];
extlen = sizeof(struct sadb_address);
extlen += PFKEY_ALIGN8(SALEN(local));
addr->sadb_address_len = PFKEY_UNIT64(extlen);
addr->sadb_address_exttype = SADB_EXT_ADDRESS_SRC;
addr->sadb_address_proto = 0;
addr->sadb_address_prefixlen = plen;
addr->sadb_address_reserved = 0;
addr++;
memcpy(addr, local, SALEN(local));
location += sizeof(struct sadb_address);
location += PFKEY_ALIGN8(SALEN(local));
addr = (struct sadb_address*)&buff[location];
extlen = sizeof(struct sadb_address);
extlen += PFKEY_ALIGN8(SALEN(target));
addr->sadb_address_len = PFKEY_UNIT64(extlen);
addr->sadb_address_exttype = SADB_EXT_ADDRESS_DST;
addr->sadb_address_proto = 0;
addr->sadb_address_prefixlen = plen;
addr->sadb_address_reserved = 0;
addr++;
memcpy(addr, target, SALEN(target));
location += sizeof(struct sadb_address);
location += PFKEY_ALIGN8(SALEN(target));
proposal = (struct sadb_prop*) &buff[location];
proposal->sadb_prop_len = PFKEY_UNIT64(sizeof(struct sadb_prop));
proposal->sadb_prop_exttype = SADB_EXT_PROPOSAL;
proposal->sadb_prop_replay = 0;
memset(proposal->sadb_prop_reserved, 0, 3);
#ifdef __WIN32__
if (send(pfkeysp[0], buff, len, 0) < 0) {
printf("pfkey_send_acquire() write error: %s", strerror(errno));
return(-1);
}
#else
if (write(pfkeysp[0], buff, len) != len) {
printf("pfkey_send_acquire() write error: %s", strerror(errno));
return(-1);
}
#endif
return(0);
}

1131
src/usermode/hip_sadb.c Normal file

File diff suppressed because it is too large Load Diff

381
src/usermode/hip_status2.c Normal file
View File

@ -0,0 +1,381 @@
/*
* Host Identity Protocol
* Copyright (C) 2005-06 the Boeing Company
*
* 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 2 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.
*
* hip_status.c
*
* Authors: Jeff Ahrenholz <jeffrey.m.ahrenholz@boeing.com>
*
* Status thread
*
*/
#ifdef __CYGWIN__
#include <windows.h>
#include <w32api/iphlpapi.h>
#endif
#include <stdio.h> /* printf() */
#ifdef __WIN32__
#include <win32/types.h>
#else
#include <unistd.h>
#include <pthread.h> /* phread_exit() */
#include <sys/uio.h> /* iovec */
#endif
#include <string.h> /* strerror() */
#include <errno.h> /* errno */
#include <hip/hip_service.h>
#include <hip/hip_types.h>
#include <hip/hip_sadb.h> /* access to SADB */
#include <hip/hip_status.h>
#include <hip/hip_funcs.h> /* pthread_mutex_lock() */
#include <win32/rtnetlink.h> /* from <linux/rtnetlink.h> */
#ifdef SMA_CRAWLER
#include <utime.h>
#endif
/*
* Local function declarations
*/
void handle_status_request(int type, char *buff, int *len);
void dump_sadb(char *buff, int *tlv_len, __u32 spi);
void dump_dst_entries(char *buff, int *tlv_len);
void dump_lsi_entries(char *buff, int *tlv_len);
void dump_all_spi(char *buff, int *tlv_len);
extern int sadb_hashfn(__u32 spi);
#define STATBUFSIZE 4096
/*
* hip_status()
*
*
*/
#ifdef __WIN32__
void hip_status(void *arg)
#else
void *hip_status(void *arg)
#endif
{
int err, s, len;
#ifdef __CYGWIN__
int from_len;
#else
socklen_t from_len;
#endif
char buff[STATBUFSIZE];
fd_set read_fdset;
struct timeval timeout;
struct sockaddr_in addr;
struct sockaddr_storage ss_from;
struct sockaddr *from = (struct sockaddr*) &ss_from;
struct status_tlv *req;
#ifdef SMA_CRAWLER
time_t last_time, now_time;
last_time = time(NULL);
printf("hip_status() thread (tid %d pid %d) started...\n",
(unsigned)pthread_self(), getpid());
#else
printf("hip_status() thread started...\n");
#endif
if ((s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
printf("Status thread socket() error: %s\n", strerror(errno));
fflush(stdout);
#ifdef __WIN32__
return;
#else
return NULL;
#endif
}
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_port = htons(WIN_STATUS_PORT);
if (bind(s, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
printf("Status thread: bind() error - %s\n", strerror(errno));
fflush(stdout);
#ifdef __WIN32__
return;
#else
return NULL;
#endif
}
while(g_state == 0) {
FD_ZERO(&read_fdset);
FD_SET((unsigned)s, &read_fdset);
timeout.tv_sec = 1;
timeout.tv_usec = 0;
#ifdef SMA_CRAWLER
now_time = time(NULL);
if (now_time - last_time > 60) {
printf("hip_status() heartbeat\n");
last_time = now_time;
utime("/usr/local/etc/hip/heartbeat_hip_status", NULL);
}
#endif
if ((err = select(s+1, &read_fdset, NULL,NULL, &timeout) < 0)) {
if (errno == EINTR)
continue;
printf("Status thread: select() error: %s.\n",
strerror(errno));
} else if (FD_ISSET(s, &read_fdset)) {
memset(buff, 0, sizeof(buff));
from_len = sizeof(struct sockaddr_storage);
if ((err = recvfrom(s, buff, sizeof(buff), 0,
from, &from_len)) < 0) {
if (err != -EINTR)
printf("Status thread: recvfrom error:"
" %s\n", strerror(errno));
continue;
}
if (err < sizeof(struct status_tlv))
continue;
req = (struct status_tlv*)buff;
len = sizeof(buff);
handle_status_request(ntohs(req->tlv_type), buff, &len);
len = sendto(s, buff, len, 0, from, from_len);
}
}
printf("hip_status() thread shutdown.\n");
fflush(stdout);
#ifndef __WIN32__
pthread_exit((void *) 0);
return(NULL);
#endif
}
/*
* a status request is normally just a type code, and the supplied buff
* will be filled with a response; if the type has a parameter, then buff
* initially contains the entire request.
*/
void handle_status_request(int type, char *buff, int *len)
{
int tlv_len=0;
struct status_tlv *t = (struct status_tlv*) buff;
__u32 spi, *spi_p;
switch(type) {
case STAT_THREADS:
t->tlv_type = htons(HIP_STATUS_REPLY_STRING);
t->tlv_len = htons(40);
t++;
sprintf((char*)t,
"Thread info not implemented yet.\n");
tlv_len = 40;
break;
case STAT_SADB:
/* read any SPI parameter */
spi = 0;
if (ntohs(t->tlv_len) == sizeof(__u32)) {
spi_p =(__u32*)&buff[sizeof(struct status_tlv)];
spi = ntohl(*spi_p);
}
dump_sadb(buff, &tlv_len, spi);
break;
case STAT_DST:
dump_dst_entries(buff, &tlv_len);
break;
case STAT_LSI:
dump_lsi_entries(buff, &tlv_len);
break;
case STAT_ALL_SPI:
dump_all_spi(buff, &tlv_len);
break;
case STAT_MIN:
case STAT_MAX:
default:
printf("<Status thread: replying with error (%d)>",
type);
t->tlv_type = htons(HIP_STATUS_REPLY_ERROR);
t->tlv_len = 0;
t++;
break;
}
t = (struct status_tlv*) ((char*)t + tlv_len);
t->tlv_type = htons(HIP_STATUS_REPLY_DONE);
t->tlv_len = 0;
t++;
*len = (char*)t - buff;
}
extern hip_sadb_entry *hip_sadb[SADB_SIZE];
extern hip_mutex_t hip_sadb_locks[SADB_SIZE];
int sockaddr_list_length(sockaddr_list *l)
{
int count = 0;
for(; l; l=l->next)
count++;
return(count);
}
void dump_sadb(char *buff, int *tlv_len, __u32 spi)
{
hip_sadb_entry *entry;
struct status_tlv *t = (struct status_tlv*)buff;
int i=0, len=0, n;
char *p;
sockaddr_list *l;
if (spi > 0)
i = sadb_hashfn(spi);
for (; i < SADB_SIZE; i++) {
pthread_mutex_lock(&hip_sadb_locks[i]);
for ( entry = hip_sadb[i]; entry; entry = entry->next ) {
if ((spi > 0) && (entry->spi != spi))
continue;
pthread_mutex_lock(&entry->rw_lock);
t->tlv_type = htons(HIP_STATUS_REPLY_SADB);
t->tlv_len = 0;
p = (char *)(t + 1);
len = 0;
ADD_ITEM(p, entry->spi, len);
ADD_ITEM(p, entry->direction, len);
ADD_ITEM(p, entry->hit_magic, len);
ADD_ITEM(p, entry->mode, len);
ADD_ITEM(p, entry->lsi, len);
ADD_ITEM(p, entry->lsi6, len);
ADD_ITEM(p, entry->a_type, len);
ADD_ITEM(p, entry->e_type, len);
ADD_ITEM(p, entry->a_keylen, len);
ADD_ITEM(p, entry->e_keylen, len);
ADD_ITEM(p, entry->lifetime, len);
ADD_ITEM(p, entry->bytes, len);
ADD_ITEM(p, entry->sequence, len);
/*ADD_ITEM(p, entry->replay_win, len);
ADD_ITEM(p, entry->replay_map, len);
ADD_ITEM(p, entry->iv, len);*/
n = sockaddr_list_length(entry->src_addrs);
ADD_ITEM(p, n, len);
n = sockaddr_list_length(entry->dst_addrs);
ADD_ITEM(p, n, len);
t->tlv_len = htons((__u16)len);
t = (struct status_tlv *)(p + len);
/* addresses */
t->tlv_type = htons(HIP_STATUS_REPLY_ADDR);
t->tlv_len = 0;
p = (char *)(t + 1);
len = 0;
for (l = entry->src_addrs; l; l=l->next)
ADD_ITEM(p, l->addr, len);
for (l = entry->dst_addrs; l; l=l->next)
ADD_ITEM(p, l->addr, len);
/* TODO: add NAT variables here */
t->tlv_len = htons((__u16)len);
t = (struct status_tlv *)(p + len);
pthread_mutex_unlock(&entry->rw_lock);
/* buffer size check */
if (((char *)t - buff) > (STATBUFSIZE - len))
break;
}
pthread_mutex_unlock(&hip_sadb_locks[i]);
/* buffer size check */
if (((char *)t - buff) > (STATBUFSIZE - len))
break;
}
*tlv_len = (char*)t - buff;
}
extern hip_sadb_dst_entry *hip_sadb_dst[SADB_SIZE];
extern hip_mutex_t hip_sadb_dst_locks[SADB_SIZE];
void dump_dst_entries(char *buff, int *tlv_len)
{
hip_sadb_dst_entry *entry;
struct status_tlv *t = (struct status_tlv*)buff;
int i, len;
char *p;
for (i=0; i < SADB_SIZE; i++) {
pthread_mutex_lock(&hip_sadb_dst_locks[i]);
for ( entry = hip_sadb_dst[i]; entry; entry = entry->next) {
pthread_mutex_lock(&entry->rw_lock);
t->tlv_type = htons(HIP_STATUS_REPLY_DST_ENTRY);
t->tlv_len = 0;
p = (char *)(t + 1);
len = 0;
ADD_ITEM(p, entry->addr, len);
ADD_ITEM(p, entry->sadb_entry->spi, len);
t->tlv_len = htons((__u16)len);
t = (struct status_tlv *)(p + len);
pthread_mutex_unlock(&entry->rw_lock);
}
pthread_mutex_unlock(&hip_sadb_dst_locks[i]);
}
*tlv_len = (char*)t - buff;
}
extern hip_lsi_entry *lsi_temp;
void dump_lsi_entries(char *buff, int *tlv_len)
{
hip_lsi_entry *l;
struct status_tlv *t = (struct status_tlv*)buff;
int len;
char *p;
for (l = lsi_temp; l; l=l->next) {
t->tlv_type = htons(HIP_STATUS_REPLY_LSI_ENTRY);
t->tlv_len = 0;
p = (char *)(t + 1);
len = 0;
ADD_ITEM(p, l->addr, len);
ADD_ITEM(p, l->lsi4, len);
ADD_ITEM(p, l->lsi6, len);
ADD_ITEM(p, l->num_packets, len);
ADD_ITEM(p, l->next_packet, len);
ADD_ITEM(p, l->send_packets, len);
ADD_ITEM(p, l->creation_time.tv_sec, len);
t->tlv_len = htons((__u16)len);
t = (struct status_tlv *)(p + len);
}
*tlv_len = (char*)t - buff;
}
/* dump all spi(s) in sadb*/
void dump_all_spi(char *buff, int *tlv_len)
{
hip_sadb_entry *entry;
struct status_tlv *t = (struct status_tlv*)buff;
int i, len;
char *p;
for (i=0; i < SADB_SIZE; i++) {
for ( entry = hip_sadb[i]; entry; entry=entry->next ) {
t->tlv_type = htons(HIP_STATUS_REPLY_ALL_SPI);
t->tlv_len = 0;
p = (char *)(t + 1);
len = 0;
ADD_ITEM(p, entry->spi, len);
t->tlv_len = htons((__u16)len);
t = (struct status_tlv *)(p + len);
}
}
*tlv_len = (char*)t - buff;
}

166
src/usermode/hip_umh_main.c Normal file
View File

@ -0,0 +1,166 @@
/*
* Host Identity Protocol
* Copyright (C) 2002-06 the Boeing Company
*
* 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 2 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.
*
* hip_umh_main.c
*
* Authors: Jeff Ahrenholz <jeffrey.m.ahrenholz@boeing.com>
* Tom Henderson <thomas.r.henderson@boeing.com>
*
* User-mode preparation for main_loop() and other functions that are common
* to both Linux and win32 user-mode versions.
*
*/
/*
* Style: KNF where possible, K&R style braces around control structures
* Style: indent using tabs-- multi-line continuation 4 spaces
* Style: no tabs in middle of lines
* Style: this code authored with tabstop=8
*/
#include <stdio.h> /* stderr, etc */
#include <string.h> /* memset() */
#include <time.h> /* time() */
#ifdef __WIN32__
#include <win32/types.h>
#include <process.h>
#include <io.h>
#else
#include <sys/socket.h> /* sock(), recvmsg(), etc */
#include <sys/time.h> /* gettimeofday() */
#include <unistd.h> /* fork(), getpid() */
#include <pthread.h>
#include <errno.h>
#include <arpa/inet.h>
#endif
#include <sys/types.h> /* getpid() support, etc */
#include <hip/hip_types.h>
#include <hip/hip_usermode.h>
#include <hip/hip_globals.h> /* g_state */
#include <hip/hip_funcs.h>
#ifdef __WIN32__
void hipd_main(void *args)
#else
void *hipd_main(void *args)
#endif
{
char *argv[10];
char *strargs;
int argc, err;
/* Convert the single void *args containing a string of program
* arguments into the standard argc with argv array.
* Must be NULL-terminated, with arguments separated by a space. */
memset(argv, 0, sizeof(argv));
argc = 1;
if (args) {
strargs = (char *) args;
argv[argc] = strargs;
if (*strargs != '\0') {
argc++;
strargs++;
}
/* scan string until NULL */
while(*strargs != '\0') {
if (*strargs == ' ') {
*strargs = '\0'; /* split into substrings by
adding NULL */
strargs++; /* point to next item */
argv[argc] = strargs;
argc++;
if (argc==10) /* stop at end of array */
break;
}
strargs++;
}
}
err = main_loop(argc, argv);
if (err == -EINTR) {
/* wait for signal handler shutdown,
* otherwise program will hang */
while (g_state==0)
#ifdef __WIN32__
Sleep(1000);
}
return;
#else
sleep(1);
}
pthread_exit((void *) 0);
return(NULL);
#endif
}
/*
* init_esp_input()
*
* Open and bind an ESP socket.
*/
int init_esp_input(int family, int proto)
{
int s, err;
struct sockaddr *local_addr;
struct sockaddr_storage local_addr_s;
local_addr = (struct sockaddr*) &local_addr_s;
if ((family != AF_INET) && (family != AF_INET6))
return(-1);
#ifdef __MACOSX__
if ((s = socket(AF_INET, SOCK_RAW, IPPROTO_DIVERT)) < 0) {
printf("init_esp_input(): socket() error\n");
printf("error: (%d) %s\n", errno, strerror(errno));
return(-1);
}
#else
if ((s = socket(family, SOCK_RAW, proto)) < 0) {
printf("init_esp_input(): %s socket() error\n"
"error: (%d) %s\n", (proto==IPPROTO_UDP) ? "UDP" : "ESP",
errno, strerror(errno));
return(-1);
}
#endif
memset(local_addr, 0, sizeof(struct sockaddr_storage));
#ifdef __MACOSX__
((struct sockaddr_in*)local_addr)->sin_family= AF_INET;
/* XXX where does this 5150 come from? */
((struct sockaddr_in*)local_addr)->sin_port = htons(5150);
((struct sockaddr_in*)local_addr)->sin_addr.s_addr = 0;
#else
local_addr->sa_family = family;
if (family == AF_INET) {
((struct sockaddr_in*)local_addr)->sin_port = \
(proto==IPPROTO_UDP) ? htons(HIP_UDP_PORT) : 0;
((struct sockaddr_in*)local_addr)->sin_addr.s_addr = INADDR_ANY;
} else {
str_to_addr((__u8*)"0::0", local_addr);
}
#endif
/* XXX shouldn't this bind() to port 50500 only for UDP ?? */
if ((err = bind(s, local_addr, SALEN(local_addr))) < 0) {
/* XXX this is broken for IPv6; bind() doesn't accept
* protocol 50, when using winsock2 or cygwin!
*/
/* if (family == AF_INET) { */
printf("init_esp_input(): bind() error\n");
printf("error: (%d) %s\n", errno, strerror(errno));
return(-1);
/* }*/
}
return(s);
}

View File

@ -0,0 +1,691 @@
/*
* Host Identity Protocol
* Copyright (C) 2002-05 the Boeing Company
*
* 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 2 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.
*
* hip_ipsec_win32.c
*
* Authors: Jeff Ahrenholz, <jeffrey.m.ahrenholz@boeing.com>
*
* Functions for communicating with the kernel IPSec implementation using
* the PF_KEYv2 messaging interface.
*
*/
#include <stdio.h> /* stderr, etc */
#include <stdlib.h> /* rand() */
#include <errno.h> /* strerror(), errno */
#include <string.h> /* memset() */
#include <time.h> /* time() */
#include <ctype.h> /* tolower() */
#ifdef __WIN32__
#include <winsock2.h>
#include <ws2tcpip.h> /* for sockaddrin_6 */
#include <io.h> /* read() */
#include <win32/types.h>
#else
#include <sys/types.h>
#include <arpa/inet.h> /* inet_addr() */
#include <sys/socket.h> /* sock(), recvmsg(), etc */
#include <unistd.h> /* write() */
#ifdef __MACOSX__
#include <netinet/in_systm.h>
#else
#include <asm/types.h>
#endif /* __MACOSX__ */
#include <netinet/in.h> /* struct sockaddr_in, etc */
#include <netinet/ip.h> /* struct iphdr */
#endif /* __WIN32__ */
#include <openssl/crypto.h> /* OpenSSL's crypto library */
#include <openssl/bn.h> /* Big Numbers */
#include <openssl/dsa.h> /* DSA support */
#include <openssl/dh.h> /* Diffie-Hellman contexts */
#include <openssl/sha.h> /* SHA1 algorithms */
#include <openssl/rand.h> /* RAND_seed() */
#ifdef __UMH__
#include <win32/pfkeyv2.h>
#else
#include "/usr/src/linux/include/linux/pfkeyv2.h" /* PF_KEY_V2 support */
#endif
#include <hip/hip_types.h>
#include <hip/hip_funcs.h> /* SALEN() */
#include <hip/hip_globals.h>
#define IPSEC_PFKEYv2_ALIGN (sizeof(uint64_t) / sizeof(uint8_t))
#define PFKEY_ALIGN8(a) (1 + (((a) - 1) | (8 - 1)))
/*
* Local function declarations
*/
int build_sa_ext(char *data, __u32 spi, __u8 state, __u8 auth, __u8 encrypt, __u32 flags);
int build_sa2_ext(char *data, __u32 mode);
int build_nat_port_ext(char *data, int type, __u16 port);
int build_lifetime_ext(char *data, int type, __u32 lifetime);
int build_address_ext(char *data, int type, struct sockaddr *addr);
int build_ident_ext(char *data, int type, struct sockaddr *addr);
int build_hit_ext(char *data, int type, uint16_t val);
int pfkey_send_hip_x1 (int sock, u_int type, u_int satype, u_int mode,
struct sockaddr *src, struct sockaddr *dst,
struct sockaddr *isrc, struct sockaddr *idst,
u_int32_t spi,
u_int32_t regid, u_int wsize, caddr_t key,
u_int e_type, u_int e_keylen, u_int a_type, u_int a_keylen,
u_int flags, u_int32_t l_alloc, u_int32_t l_bytes,
u_int32_t l_addtime, u_int32_t l_usetime, u_int32_t seqno,
u_int8_t l_natt_type, u_int16_t l_natt_sport,
u_int16_t l_natt_dport, struct sockaddr *l_natt_oa,
u_int16_t hitmagic)
{
int err, location=0, len=0;
struct sadb_key *pfkey_key;
struct sadb_msg *pfkey_msg;
char buff[SADB_MSG_SIZE_ADD];
location = 0;
/* message header */
pfkey_msg = (struct sadb_msg*) &buff[0];
pfkey_msg->sadb_msg_version = PF_KEY_V2;
pfkey_msg->sadb_msg_type = type;
pfkey_msg->sadb_msg_errno = 0;
pfkey_msg->sadb_msg_satype = satype;
pfkey_msg->sadb_msg_len = -1; /* Will fill in below */
pfkey_msg->sadb_msg_reserved = 0;
pfkey_msg->sadb_msg_seq = seqno;
pfkey_msg->sadb_msg_pid = regid; /* OTB -- spinat */
len = sizeof(struct sadb_msg);
location += len;
/* SA extension */
location += build_sa_ext(&buff[location], spi,
SADB_SASTATE_MATURE, (__u8)a_type, (__u8)e_type, 0);
/* SA2 extension (for mode) */
if (mode) {
location += build_sa2_ext(&buff[location], mode);
}
/* NAT source/destination port */
if (l_natt_sport > 0)
location += build_nat_port_ext(&buff[location],
SADB_X_EXT_NAT_T_SPORT, l_natt_sport);
if (l_natt_dport > 0)
location += build_nat_port_ext(&buff[location],
SADB_X_EXT_NAT_T_DPORT, l_natt_dport);
/* lifetime extension */
location += build_lifetime_ext(&buff[location],
SADB_EXT_LIFETIME_HARD, l_addtime);
/* source address extension */
location += build_address_ext(&buff[location], SADB_EXT_ADDRESS_SRC,
src);
/* destination address extension */
location += build_address_ext(&buff[location], SADB_EXT_ADDRESS_DST,
dst);
/* inner source/destination address extensions */
if (isrc && idst) {
location += build_ident_ext(&buff[location],
SADB_EXT_IDENTITY_SRC, isrc);
location += build_ident_ext(&buff[location],
SADB_EXT_IDENTITY_DST, idst);
}
/* authentication key extension */
pfkey_key = (struct sadb_key*) &buff[location];
memset(pfkey_key, 0, sizeof(struct sadb_key));
location += sizeof(struct sadb_key); /* 8 bytes */
/*
* With 20 byte auth key, need 8 + 20 + 4 (pad) to
* end up on an 8 byte boundary
*/
pfkey_key->sadb_key_len = eight_byte_align(sizeof(struct sadb_key) +
a_keylen) / IPSEC_PFKEYv2_ALIGN;
pfkey_key->sadb_key_exttype = SADB_EXT_KEY_AUTH;
pfkey_key->sadb_key_bits = a_keylen * 8; /* 160 bits */
pfkey_key->sadb_key_reserved = 0;
/* key[enc_key|auth_key] */
memcpy(&buff[location], &key[e_keylen], a_keylen);
location += a_keylen;
memset(&buff[location], 0, 4); /* padding to 24 bytes */
location += 4;
/* encryption key extension */
pfkey_key = (struct sadb_key*) &buff[location];
memset(pfkey_key, 0, sizeof(struct sadb_key));
location += sizeof(struct sadb_key);
pfkey_key->sadb_key_len = eight_byte_align(sizeof(struct sadb_key) +
e_keylen) / IPSEC_PFKEYv2_ALIGN;
pfkey_key->sadb_key_exttype = SADB_EXT_KEY_ENCRYPT;
pfkey_key->sadb_key_reserved = 0;
pfkey_key->sadb_key_bits = e_keylen*8;
/* key[enc_key|auth_key] */
memcpy(&buff[location], &key[0], e_keylen);
location += e_keylen;
/* insert ext hdr for hip_hit */
location += build_hit_ext(&buff[location], SADB_EXT_HIT, hitmagic);
/*
implementations that don't support the hit ext hdr SHOULD
ignore it.
*/
/* complete the header */
len = location;
pfkey_msg->sadb_msg_len = len / IPSEC_PFKEYv2_ALIGN;
/* send the SADB_ADD message to the kernel */
#ifdef __WIN32__
err = send(sock, (char *)pfkey_msg, len, 0);
#else
err = write(sock, (char *)pfkey_msg, len);
#endif
if (err < 1) {
fprintf(stderr, "sadb_add: pfkey write() error: %s.\n",
strerror(errno));
}
return(err);
}
int pfkey_send_rea (int sock, u_int type, u_int satype,
struct sockaddr *src, struct sockaddr *dst, u_int32_t spi,
u_int e_type, u_int a_type, u_int flags, u_int32_t seqno)
{
struct sadb_msg *pfkey_msg;
int len, err=0, location;
char buff[512];
location = 0;
memset(buff, 0, sizeof(buff));
/* message header */
pfkey_msg = (struct sadb_msg*)&buff[0];
pfkey_msg->sadb_msg_version = PF_KEY_V2;
pfkey_msg->sadb_msg_type = type;
pfkey_msg->sadb_msg_errno = 0;
pfkey_msg->sadb_msg_satype = satype;
pfkey_msg->sadb_msg_len = -1; /* set later */
pfkey_msg->sadb_msg_reserved = 0;
pfkey_msg->sadb_msg_seq = seqno;
pfkey_msg->sadb_msg_pid = 0;
location = sizeof(struct sadb_msg);
/* SA extension */
location += build_sa_ext(&buff[location], spi,
SADB_SASTATE_MATURE, (__u8)a_type, (__u8)e_type, 0);
/* src address extension */
location += build_address_ext(&buff[location],
SADB_EXT_ADDRESS_SRC, src);
/* dst address extension */
location += build_address_ext(&buff[location],
SADB_EXT_ADDRESS_DST, dst);
len = location;
pfkey_msg->sadb_msg_len = len / IPSEC_PFKEYv2_ALIGN;
#ifdef __WIN32__
err = send(sock, (char *)pfkey_msg, len, 0);
#else
err = write(sock, pfkey_msg, len);
#endif
if (err < 1) {
fprintf(stderr, "sadb_readdress: PF_KEY write() error: %s.\n",
strerror(errno));
return(err);
}
return(0);
}
/* used to establish direction */
int pfkey_send_spdadd(int so, struct sockaddr *src, u_int prefs,
struct sockaddr *dst, u_int prefd, u_int proto,
caddr_t pol, int policylen, u_int32_t seq)
{
struct sadb_msg pfkey_msgh;
struct sadb_x_policy *policy;
int len, err=0, location;
char buff[1024];
location = 0;
len = sizeof(struct sadb_msg);
len += sizeof(struct sadb_sa);
len += 2*sizeof(struct sadb_address);
len += 2*PFKEY_ALIGN8(SALEN(src));
memset(buff, 0, len);
/* message header */
pfkey_msgh.sadb_msg_version = PF_KEY_V2;
pfkey_msgh.sadb_msg_type = SADB_X_SPDADD;
pfkey_msgh.sadb_msg_errno = 0;
pfkey_msgh.sadb_msg_satype = SADB_SATYPE_ESP;
pfkey_msgh.sadb_msg_len = len / IPSEC_PFKEYv2_ALIGN;
pfkey_msgh.sadb_msg_reserved = 0;
pfkey_msgh.sadb_msg_seq = seq;
pfkey_msgh.sadb_msg_pid = 0;
len = sizeof(struct sadb_msg);
memcpy(&buff[0], &pfkey_msgh, len);
location += len;
/* source flow extension */
location += build_address_ext( &buff[location],
SADB_EXT_ADDRESS_SRC, src);
/* destination flow extension */
location += build_address_ext( &buff[location],
SADB_EXT_ADDRESS_DST, dst);
/* policy extension - already built by ipsec_set_policy() */
policy = (struct sadb_x_policy *)&buff[location];
memcpy(policy, pol, sizeof(struct sadb_x_policy));
location += sizeof(struct sadb_x_policy);
#ifdef __WIN32__
err = send(so, buff, location, 0);
#else
err = write(so, buff, location);
#endif
if (err < 1){
fprintf(stderr, "sadb_add_policy: pfkey write() error: %s.\n",
strerror(errno));
}
return(err);
}
int pfkey_send_spddelete(int so, struct sockaddr *src, u_int prefs,
struct sockaddr *dst, u_int prefd, u_int proto,
caddr_t policy, int policylen, u_int32_t seq)
{
/* This is currently a no-op function. */
return(0);
}
int pfkey_send_delete(int so, u_int satype, u_int mode,
struct sockaddr *src, struct sockaddr *dst,
u_int32_t spi)
{
struct sadb_msg pfkey_msgh;
int len, err=0, location;
char buff[SADB_MSG_SIZE_DELETE]; /* 80 */
location = 0;
len = sizeof(struct sadb_msg);
len += sizeof(struct sadb_sa);
len += 2*sizeof(struct sadb_address);
len += 2*sizeof(struct sockaddr);
memset(buff, 0, len);
/* message header */
pfkey_msgh.sadb_msg_version = PF_KEY_V2;
pfkey_msgh.sadb_msg_type = SADB_DELETE;
pfkey_msgh.sadb_msg_errno = 0;
pfkey_msgh.sadb_msg_satype = satype;
pfkey_msgh.sadb_msg_len = len / IPSEC_PFKEYv2_ALIGN;
pfkey_msgh.sadb_msg_reserved = 0;
pfkey_msgh.sadb_msg_seq = 0;
pfkey_msgh.sadb_msg_pid = 0;
len = sizeof(struct sadb_msg);
memcpy(&buff[0], &pfkey_msgh, len);
location += len;
/* SA extension */
location += build_sa_ext(&buff[location], spi, 0, 0, 0, 0);
/* source flow extension */
location += build_address_ext(&buff[location],
SADB_EXT_ADDRESS_SRC, src);
/* destination flow extension */
location += build_address_ext(&buff[location],
SADB_EXT_ADDRESS_DST, dst);
/* send SADB_DELETE message to the kernel */
#ifdef __WIN32__
err = send(so, buff, location, 0);
#else
err = write(so, buff, location);
#endif
if (err < 1){
fprintf(stderr, "sadb_delete: pfkey write() error: %s.\n",
strerror(errno));
}
return(err);
}
int pfkey_send_register(int so, u_int satype)
{
struct sadb_msg pfkey_msgh;
int len, err=0;
memset(&pfkey_msgh, 0, sizeof(struct sadb_msg));
/* build the PF_KEY message */
pfkey_msgh.sadb_msg_version = PF_KEY_V2;
pfkey_msgh.sadb_msg_type = SADB_REGISTER;
pfkey_msgh.sadb_msg_errno = 0;
pfkey_msgh.sadb_msg_satype = satype;
pfkey_msgh.sadb_msg_len = sizeof(struct sadb_msg) / IPSEC_PFKEYv2_ALIGN;
pfkey_msgh.sadb_msg_reserved = 0;
pfkey_msgh.sadb_msg_seq = 0;
pfkey_msgh.sadb_msg_pid = 0;
len = sizeof(pfkey_msgh);
/* send SADB_REGISTER message to the kernel */
#ifdef __WIN32__
err = send(so, (char *)&pfkey_msgh, len, 0);
#else
err = write(so, &pfkey_msgh, len);
#endif
if (err < 1) {
fprintf(stderr, "sadb_register: pfkey write() error: %s.\n",
strerror(errno));
}
return(err);
}
int pfkey_send_getspi(int so, u_int satype, u_int mode,
struct sockaddr *src, struct sockaddr *dst, u_int32_t min,
u_int32_t max, u_int32_t reqid, u_int32_t seq)
{
int err, location=0, len=0;
struct sadb_msg *pfkey_msg;
struct sadb_spirange *spirange;
char buff[256];
location = 0;
/* message header */
pfkey_msg = (struct sadb_msg*) &buff[0];
pfkey_msg->sadb_msg_version = PF_KEY_V2;
pfkey_msg->sadb_msg_type = SADB_GETSPI;
pfkey_msg->sadb_msg_errno = 0;
pfkey_msg->sadb_msg_satype = satype;
pfkey_msg->sadb_msg_len = -1;
pfkey_msg->sadb_msg_reserved = 0;
pfkey_msg->sadb_msg_seq = seq;
pfkey_msg->sadb_msg_pid = 0;
len = sizeof(struct sadb_msg);
location += len;
/* spirange extension */
spirange = (struct sadb_spirange*) &buff[location];
spirange->sadb_spirange_len = \
(sizeof(struct sadb_spirange) / IPSEC_PFKEYv2_ALIGN);
spirange->sadb_spirange_exttype = SADB_EXT_SPIRANGE;
spirange->sadb_spirange_min = min;
spirange->sadb_spirange_max = max;
spirange->sadb_spirange_reserved = 0;
location += sizeof(struct sadb_spirange);
/* complete the header */
len = location;
pfkey_msg->sadb_msg_len = len / IPSEC_PFKEYv2_ALIGN;
/* send the SADB_GET message to the kernel */
#ifdef __WIN32__
err = send(so, (char *)pfkey_msg, len, 0);
#else
err = write(so, (char *)pfkey_msg, len);
#endif
if (err < 1) {
fprintf(stderr, "sadb_getspi: pfkey write() error: %s.\n",
strerror(errno));
}
return(err);
}
int pfkey_send_get(int so, u_int satype, u_int mode,
struct sockaddr *src, struct sockaddr *dst, u_int32_t spi)
{
int err, location=0, len=0;
struct sadb_msg *pfkey_msg;
char buff[256];
location = 0;
/* message header */
pfkey_msg = (struct sadb_msg*) &buff[0];
pfkey_msg->sadb_msg_version = PF_KEY_V2;
pfkey_msg->sadb_msg_type = SADB_GET;
pfkey_msg->sadb_msg_errno = 0;
pfkey_msg->sadb_msg_satype = satype;
pfkey_msg->sadb_msg_len = -1;
pfkey_msg->sadb_msg_reserved = 0;
pfkey_msg->sadb_msg_seq = 0;
pfkey_msg->sadb_msg_pid = 0;
len = sizeof(struct sadb_msg);
location += len;
/* SA extension */
location += build_sa_ext(&buff[location], spi,
SADB_SASTATE_MATURE, 0, 0, 0);
/* source address extension */
location += build_address_ext(&buff[location],
SADB_EXT_ADDRESS_SRC, src);
/* destination address extension */
location += build_address_ext(&buff[location],
SADB_EXT_ADDRESS_DST, dst);
/* complete the header */
len = location;
pfkey_msg->sadb_msg_len = len / IPSEC_PFKEYv2_ALIGN;
/* send the SADB_GET message to the kernel */
#ifdef __WIN32__
err = send(so, (char *)pfkey_msg, len, 0);
#else
err = write(so, (char *)pfkey_msg, len);
#endif
if (err < 1) {
fprintf(stderr, "sadb_get: pfkey write() error: %s.\n",
strerror(errno));
}
return(err);
}
int __ipsec_errcode;
const char *ipsec_strerror (void)
{
return(0);
}
int ipsec_get_policylen (caddr_t policy)
{
return(sizeof(struct sadb_x_policy));
}
caddr_t ipsec_set_policy (char *msg, int msglen)
{
struct sadb_x_policy *policy;
int len = sizeof(struct sadb_x_policy);
if (msglen < 2)
return NULL;
policy = (struct sadb_x_policy*) malloc(len);
memset(policy, 0, len);
policy->sadb_x_policy_exttype = SADB_X_EXT_POLICY;
policy->sadb_x_policy_len = (len / IPSEC_PFKEYv2_ALIGN);
/* direction: 2 == outgoing, 1 == incoming */
if (strncmp(msg, "in", 2)==0) {
policy->sadb_x_policy_dir = 1;
} else {
policy->sadb_x_policy_dir = 2;
}
return((caddr_t)policy);
}
/*****************************************
* Message extension builders *
*****************************************/
/*
* build an address extension
*/
int build_address_ext(char *data, int type, struct sockaddr *addr)
{
struct sadb_address *pfkey_addr;
int addr_len, len, plen;
plen = (addr->sa_family == AF_INET) ? (sizeof(struct in_addr) << 3) :
(sizeof(struct in6_addr) << 3);
addr_len = SALEN(addr);
pfkey_addr = (struct sadb_address*) data;
pfkey_addr->sadb_address_len = PFKEY_ALIGN8(sizeof(struct sadb_address)
+ addr_len) / IPSEC_PFKEYv2_ALIGN;
pfkey_addr->sadb_address_exttype = type;
pfkey_addr->sadb_address_proto = IPPROTO_ESP;
pfkey_addr->sadb_address_prefixlen = plen;
pfkey_addr->sadb_address_reserved = 0;
len = sizeof(struct sadb_address);
memcpy(&data[len], addr, addr_len);
len += addr_len;
return(PFKEY_ALIGN8(len));
}
/*
* build an identity extension
*/
int build_ident_ext(char *data, int type, struct sockaddr *addr)
{
struct sadb_ident *pfkey_ident;
int addr_len, len;
addr_len = SALEN(addr);
pfkey_ident = (struct sadb_ident*) data;
pfkey_ident->sadb_ident_len = PFKEY_ALIGN8(sizeof(struct sadb_ident) +
addr_len) / IPSEC_PFKEYv2_ALIGN;
pfkey_ident->sadb_ident_exttype = type;
pfkey_ident->sadb_ident_type = 0;
pfkey_ident->sadb_ident_reserved = 0;
pfkey_ident->sadb_ident_id = 0;
len = sizeof(struct sadb_ident);
memcpy(&data[len], addr, addr_len);
len += addr_len;
return(PFKEY_ALIGN8(len));
}
/*
* build SA extension
*/
int build_sa_ext(char *data, __u32 spi, __u8 state, __u8 auth, __u8 encrypt, __u32 flags)
{
struct sadb_sa *pfkey_sa;
pfkey_sa = (struct sadb_sa*) data;
pfkey_sa->sadb_sa_len = sizeof(struct sadb_sa) / IPSEC_PFKEYv2_ALIGN;
pfkey_sa->sadb_sa_exttype = SADB_EXT_SA;
pfkey_sa->sadb_sa_spi = spi; /* SPI is already in network byte order */
pfkey_sa->sadb_sa_replay = 0;
pfkey_sa->sadb_sa_state = state;
pfkey_sa->sadb_sa_auth = auth;
pfkey_sa->sadb_sa_encrypt = encrypt;
pfkey_sa->sadb_sa_flags = flags;
return(sizeof(struct sadb_sa));
}
/*
* build SA2 extension
*/
int build_sa2_ext(char *data, __u32 mode)
{
struct sadb_x_sa2 *pfkey_sa2;
pfkey_sa2 = (struct sadb_x_sa2*) data;
pfkey_sa2->sadb_x_sa2_len = sizeof(struct sadb_x_sa2) \
/ IPSEC_PFKEYv2_ALIGN;
pfkey_sa2->sadb_x_sa2_exttype = SADB_X_EXT_SA2;
pfkey_sa2->sadb_x_sa2_mode = (__u8)mode; /* this is all we care about */
pfkey_sa2->sadb_x_sa2_reserved1 = 0;
pfkey_sa2->sadb_x_sa2_reserved2 = 0;
pfkey_sa2->sadb_x_sa2_sequence = 0;
pfkey_sa2->sadb_x_sa2_reqid = 0;
return(sizeof(struct sadb_x_sa2));
}
/*
* build nat port extension
*/
int build_nat_port_ext(char *data, int type, __u16 port)
{
struct sadb_x_nat_t_port *pfkey_nat;
pfkey_nat = (struct sadb_x_nat_t_port*) data;
pfkey_nat->sadb_x_nat_t_port_len = sizeof(struct sadb_x_nat_t_port) \
/ IPSEC_PFKEYv2_ALIGN;
pfkey_nat->sadb_x_nat_t_port_exttype = (__u16)type;
pfkey_nat->sadb_x_nat_t_port_port = htons(port);
pfkey_nat->sadb_x_nat_t_port_reserved = 0;
return(sizeof(struct sadb_x_nat_t_port));
}
/*
* build lifetime extension
*/
int build_lifetime_ext(char *data, int type, __u32 lifetime)
{
struct sadb_lifetime *pfkey_lifetime;
pfkey_lifetime = (struct sadb_lifetime*) data;
pfkey_lifetime->sadb_lifetime_len = sizeof(struct sadb_lifetime) /
IPSEC_PFKEYv2_ALIGN;
pfkey_lifetime->sadb_lifetime_exttype = type;
pfkey_lifetime->sadb_lifetime_allocations = 0;
pfkey_lifetime->sadb_lifetime_bytes = 0;
pfkey_lifetime->sadb_lifetime_addtime = lifetime;
pfkey_lifetime->sadb_lifetime_usetime = 0;
return(sizeof(struct sadb_lifetime));
}
/*
* * build hit extension HIT_BITSIZE / 8
*/
int build_hit_ext(char *data, int type, uint16_t val)
{
struct sadb_hit *pfkey_hit;
pfkey_hit = (struct sadb_hit*) data;
pfkey_hit->sadb_hit_len = sizeof(struct sadb_hit)/IPSEC_PFKEYv2_ALIGN;
pfkey_hit->sadb_hit_exttype = type;
pfkey_hit->sadb_hit = val;
return(sizeof(struct sadb_hit));
}

View File

@ -0,0 +1,7 @@
INC=-I../../include -I/usr/include/libxml2
test_spd: test_cfgapi.c hip_cfg_api.c
gcc -Wall -g ${INC} -o test_hipcfg \
test_cfgapi.c hip_cfg_api.c -ldl -lssl -lxml2
clean:
rm -f *.o
rm -f test_hipcfg

View File

@ -0,0 +1,213 @@
#include <dlfcn.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <hip/hip_cfg_api.h>
/* hip ACL */
int (*hipcfg_init_p)(struct hip_conf *hc) = NULL;
int (*hipcfg_allowed_peers_p)(const hip_hit hit1, const hip_hit hit2) = NULL;
int (*hipcfg_peers_allowed_p)(hip_hit *hits1, hip_hit *hits2, int max_cnt) = NULL;
/* endbox config */
int (*hipcfg_getEndboxByLegacyNode_p)(const struct sockaddr *host, struct sockaddr *eb) = NULL;
int (*hipcfg_getLlipByEndbox_p)(const struct sockaddr *eb, struct sockaddr *llip) = NULL;
int (*hipcfg_getLegacyNodesByEndbox_p)(const struct sockaddr *eb, struct sockaddr_storage *hosts, int size) = NULL;
int (*hipcfg_verifyCert_p)(const char *url, const hip_hit hit) = NULL;
int (*hipcfg_getLocalCertUrl_p)(char *url, int size) = NULL;
int (*hipcfg_postLocalCert_p)(const char *hit) = NULL;
hi_node *(*hipcfg_getMyHostId_p)() = NULL;
int (*hipcfg_getPeerNodes_p)(struct peer_node *peerNodes, int max_count) = NULL;
int hipcfg_init(char *dlname, struct hip_conf *hc)
{
void *module;
module = dlopen(dlname, RTLD_NOW);
if(!module) {
fprintf(stderr, "Open %s error: %s\n", dlname, dlerror());
return -1;
}
printf("loading %s succeed.\n", dlname);
hipcfg_init_p=dlsym(module, hipcfg_init_fn);
if(hipcfg_init_p==NULL)
{
fprintf(stderr, "error loading function %s: %s\n", hipcfg_init_fn, dlerror());
return -1;
}
printf("loading %s succeed.\n", hipcfg_init_fn);
hipcfg_allowed_peers_p = dlsym(module, hipcfg_allowed_peers_fn);
if(hipcfg_allowed_peers_p==NULL)
{
fprintf(stderr, "error loading function %s: %s\n", hipcfg_allowed_peers_fn, dlerror());
return -1;
}
printf("loading %s succeed.\n", hipcfg_allowed_peers_fn);
hipcfg_peers_allowed_p = dlsym(module, hipcfg_peers_allowed_fn);
if(hipcfg_peers_allowed_p==NULL)
{
fprintf(stderr, "error loading function %s: %s\n", hipcfg_peers_allowed_fn, dlerror());
return -1;
}
printf("loading %s succeed.\n", hipcfg_peers_allowed_fn);
hipcfg_getEndboxByLegacyNode_p = dlsym(module, hipcfg_getEndboxByLegacyNode_fn);
if(hipcfg_getEndboxByLegacyNode_p==NULL)
{
fprintf(stderr, "error loading function %s: %s\n", hipcfg_getEndboxByLegacyNode_fn, dlerror());
return -1;
}
printf("loading %s succeed.\n", hipcfg_getEndboxByLegacyNode_fn);
hipcfg_getLlipByEndbox_p = dlsym(module, hipcfg_getLlipByEndbox_fn);
if(hipcfg_getLlipByEndbox_p==NULL)
{
fprintf(stderr, "error loading function %s: %s\n", hipcfg_getLlipByEndbox_fn, dlerror());
return -1;
}
printf("loading %s succeed.\n", hipcfg_getLlipByEndbox_fn);
hipcfg_getLegacyNodesByEndbox_p = dlsym(module, hipcfg_getLegacyNodesByEndbox_fn);
if(hipcfg_getLegacyNodesByEndbox_p==NULL)
{
fprintf(stderr, "error loading function %s: %s\n", hipcfg_getLegacyNodesByEndbox_fn, dlerror());
return -1;
}
printf("loading %s succeed.\n", hipcfg_getLegacyNodesByEndbox_fn);
hipcfg_verifyCert_p = dlsym(module, hipcfg_verifyCert_fn);
if(hipcfg_verifyCert_p==NULL)
{
fprintf(stderr, "error loading function %s: %s\n", hipcfg_verifyCert_fn, dlerror());
return -1;
}
hipcfg_getLocalCertUrl_p = dlsym(module, hipcfg_getLocalCertUrl_fn);
if(hipcfg_getLocalCertUrl_p==NULL)
{
fprintf(stderr, "error loading function %s: %s\n", hipcfg_getLocalCertUrl_fn, dlerror());
return -1;
}
hipcfg_postLocalCert_p = dlsym(module, hipcfg_postLocalCert_fn);
if(hipcfg_postLocalCert_p==NULL)
{
fprintf(stderr, "error loading function %s: %s\n", hipcfg_postLocalCert_fn, dlerror());
return -1;
}
printf("loading %s succeed.\n", hipcfg_verifyCert_fn);
hipcfg_getMyHostId_p = dlsym(module, hipcfg_getMyHostId_fn);
if(hipcfg_getMyHostId_p==NULL)
{
fprintf(stderr, "error loading function %s: %s\n", hipcfg_getMyHostId_fn, dlerror());
return -1;
}
printf("loading %s succeed.\n", hipcfg_getMyHostId_fn);
hipcfg_getPeerNodes_p = dlsym(module, hipcfg_getPeerNodes_fn);
if(hipcfg_getPeerNodes_p==NULL)
{
fprintf(stderr, "error loading function %s: %s\n", hipcfg_getPeerNodes_fn, dlerror());
return -1;
}
printf("loading %s succeed.\n", hipcfg_getPeerNodes_fn);
return (*hipcfg_init_p)(hc);
}
int hipcfg_allowed_peers(const hip_hit hit1, const hip_hit hit2)
{
if(hipcfg_allowed_peers_p==NULL){
fprintf(stderr, "%s not initialized\n", hipcfg_allowed_peers_fn);
return 0;
}
return (*hipcfg_allowed_peers_p)(hit1, hit2);
}
int hipcfg_peers_allowed(hip_hit *hits1, hip_hit *hits2, int max_cnt)
{
if(hipcfg_peers_allowed_p==NULL){
fprintf(stderr, "%s not initialized\n", hipcfg_peers_allowed_fn);
return 0;
}
return (*hipcfg_peers_allowed_p)(hits1, hits2, max_cnt);
}
int hipcfg_getEndboxByLegacyNode(const struct sockaddr *host, struct sockaddr *eb)
{
if(hipcfg_getEndboxByLegacyNode_p==NULL){
fprintf(stderr, "%s not initialized\n", hipcfg_getEndboxByLegacyNode_fn);
return 0;
}
return (*hipcfg_getEndboxByLegacyNode_p)(host, eb);
}
int hipcfg_getLlipByEndbox(const struct sockaddr *eb, struct sockaddr *llip)
{
if(hipcfg_getLlipByEndbox_p==NULL){
fprintf(stderr, "%s not initialized\n", hipcfg_getLlipByEndbox_fn);
return 0;
}
return (*hipcfg_getLlipByEndbox_p)(eb, llip);
}
int hipcfg_getLegacyNodesByEndbox(const struct sockaddr *eb, struct sockaddr_storage *hosts, int size)
{
if(hipcfg_getLegacyNodesByEndbox_p == NULL) {
fprintf(stderr, "%s not initialized\n", hipcfg_getLegacyNodesByEndbox_fn);
return 0;
}
return (*hipcfg_getLegacyNodesByEndbox_p)(eb, hosts, size);
}
int hipcfg_verifyCert(const char *url, const hip_hit hit)
{
if(hipcfg_verifyCert_p == NULL) {
fprintf(stderr, "%s not initialized\n", hipcfg_verifyCert_fn);
return 0;
}
return (*hipcfg_verifyCert_p)(url, hit);
}
int hipcfg_getLocalCertUrl(char *url, int size)
{
if(hipcfg_getLocalCertUrl_p == NULL) {
fprintf(stderr, "%s not initialized\n", hipcfg_getLocalCertUrl_fn);
return 0;
}
return (*hipcfg_getLocalCertUrl_p)(url, size);
}
int hipcfg_postLocalCert(const char *hit)
{
if(hipcfg_postLocalCert_p == NULL) {
fprintf(stderr, "%s not initialized\n", hipcfg_postLocalCert_fn);
return 0;
}
return (*hipcfg_postLocalCert_p)(hit);
}
hi_node *hipcfg_getMyHostId()
{
if(hipcfg_getMyHostId_p == NULL) {
fprintf(stderr, "%s not initialized\n", hipcfg_getMyHostId_fn);
return 0;
}
return (*hipcfg_getMyHostId_p)();
}
int hipcfg_getPeerNodes(struct peer_node *peerNodes, int max_count)
{
if(hipcfg_getPeerNodes_p == NULL) {
fprintf(stderr, "%s not initialized\n", hipcfg_getPeerNodes_fn);
return 0;
}
return (*hipcfg_getPeerNodes_p)(peerNodes, max_count);
}

View File

@ -0,0 +1,4 @@
#!/bin/sh
LD_LIBRARY_PATH=/root/sc/lib:/home/jfang/hip/src/cfg-ldap:$LD_LIBRARY_PATH
export LD_LIBRARY_PATH
./test_hipcfg

View File

@ -0,0 +1,412 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ether.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <fcntl.h>
#include <openssl/ssl.h>
#include <libxml/tree.h>
#include <hip/hip_cfg_api.h>
#define SA2IP(x) (((struct sockaddr*)x)->sa_family==AF_INET) ? \
(void*)&((struct sockaddr_in*)x)->sin_addr : \
(void*)&((struct sockaddr_in6*)x)->sin6_addr
#define SALEN(x) (((struct sockaddr*)x)->sa_family==AF_INET) ? \
sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6)
#define SAIPLEN(x) (((struct sockaddr*)x)->sa_family==AF_INET) ? 4 : 16
#define SA(x) ((struct sockaddr*)x)
int hit2hitstr(char *hit_str, hip_hit hit)
{
struct sockaddr *addr;
struct sockaddr_storage ss_addr;
addr = (struct sockaddr*) &ss_addr;
memset(&ss_addr, 0, sizeof(struct sockaddr_storage));
ss_addr.ss_family = AF_INET6;
memcpy(SA2IP(&ss_addr), hit, SAIPLEN(&ss_addr));
return(inet_ntop(addr->sa_family, SA2IP(addr), hit_str, INET6_ADDRSTRLEN)==NULL);
}
int str_to_addr(const char *data, struct sockaddr *addr)
{
return(inet_pton(addr->sa_family, (char*)data, SA2IP(addr)));
}
int hex_to_bin(char *src, char *dst, int dst_len)
{
char hex[] = "0123456789abcdef";
char hexcap[] = "0123456789ABCDEF";
char *p, c;
int src_len, total, i, val;
unsigned char o;
if ((!src) || (!dst))
return(-1);
src_len = strlen(src);
if (dst_len > src_len)
return(-1);
/* chop any '0x' prefix */
if ((src[0]=='0') && (src[1]=='x')) {
src += 2;
src_len -= 2;
}
/* convert requested number of bytes from hex to binary */
total = 0;
for (i=0; (i < src_len) && (total < dst_len) ; i+=2) {
c = src[i];
if ((p = strchr(hex, c)) == NULL) {
if ((p = strchr(hexcap, c)) == NULL) {
continue;
}
val = p - hexcap;
} else {
val = p - hex;
}
if (val < 0 || val > 15) {
return(-1);
}
o = val << 4;
/* least significant nibble */
c = src[i+1];
if ((p = strchr(hex, c)) == NULL) {
if ((p = strchr(hexcap, c)) == NULL) {
continue;
}
val = p - hexcap;
} else {
val = p - hex;
}
if (val < 0 || val > 15) {
return(-1);
}
o += val;
dst[total] = o;
total++;
if (total >= src_len)
total = dst_len;
}
return total;
}
int hitstr2hit(hip_hit hit, char *hit_str)
{
struct sockaddr *addr;
struct sockaddr_storage ss_addr;
addr = (struct sockaddr*) &ss_addr;
if(strchr(hit_str, ':')){
memset(addr, 0,sizeof(struct sockaddr_storage));
addr->sa_family = AF_INET6;
if(str_to_addr(hit_str, addr) <= 0) {
return -1;
}
memcpy(hit, SA2IP(addr), HIT_SIZE);
return 0;
}
return hex_to_bin(hit_str, (char *)hit, HIT_SIZE);
}
/*
* function read_conf_file()
* Load configuration options from the XML file
* stored in hip.conf
*/
int read_conf_file(char *filename, struct hip_conf *hc)
{
xmlDocPtr doc = NULL;
xmlNodePtr node = NULL;
char *data;
doc = xmlParseFile(filename);
if (doc == NULL)
return(-1);
node = xmlDocGetRootElement(doc);
for (node = node->children; node; node = node->next)
{
data = (char *)xmlNodeGetContent(node);
if (strcmp((char *)node->name, "text")==0) {
;
} else if (strcmp((char *)node->name, "comment")==0) {
;
} else if (strcmp((char*)node->name, "use_smartcard")==0){
if (strncmp(data, "yes", 3)==0)
hc->use_smartcard = TRUE;
else
hc->use_smartcard = FALSE;
} else if (strcmp((char*)node->name,
"peer_certificate_required")==0){
if (strncmp(data, "yes", 3)==0)
hc->peer_certificate_required = TRUE;
else
hc->peer_certificate_required = FALSE;
} else if (strcmp((char*)node->name,
"use_local_known_identities")==0){
if (strncmp(data, "yes", 3)==0)
hc->use_local_known_identities = TRUE;
else
hc->use_local_known_identities = FALSE;
} else if (strcmp((char*)node->name, "cfg_serv_host")==0){
hc->cfg_serv_host = malloc(strlen(data)+1);
if (!hc->cfg_serv_host)
printf("Warning: HCNF.cfg_serv_host malloc error!\n");
else
strcpy(hc->cfg_serv_host, data);
} else if (strcmp((char *)node->name, "cfg_serv_port")==0) {
sscanf(data, "%d", &hc->cfg_serv_port);
} else if (strcmp((char*)node->name, "cfg_serv_basedn")==0){
hc->cfg_serv_basedn = malloc(strlen(data)+1);
if (!hc->cfg_serv_basedn)
printf("Warning: HCNF.cfg_serv_basedn malloc " "error!\n");
else
strcpy(hc->cfg_serv_basedn, data);
} else if (strcmp((char*)node->name, "cfg_serv_login_id")==0){
hc->cfg_serv_login_id = malloc(strlen(data)+1);
if (!hc->cfg_serv_login_id)
printf("Warning: HCNF.cfg_serv_login_id malloc " "error!\n");
else
strcpy(hc->cfg_serv_login_id, data);
} else if (strcmp((char*)node->name, "cfg_serv_login_pwd")==0){
hc->cfg_serv_login_pwd = malloc(strlen(data)+1);
if (!hc->cfg_serv_login_pwd)
printf("Warning: HCNF.cfg_serv_login_pwd malloc " "error!\n");
else
strcpy(hc->cfg_serv_login_pwd, data);
} else if (strlen((char *)node->name)) {
;
}
xmlFree(data);
}
xmlFreeDoc(doc);
return(0);
}
int main(void) {
int rc, i;
hip_hit hit1;
hip_hit hit2;
struct sockaddr_storage host_ss;
struct sockaddr_storage eb_ss;
struct sockaddr *host_p;
struct sockaddr *eb_p;
char host_s[64];
char eb_s[64];
struct sockaddr_storage hosts[5];
int hosts_cnt = 5;
char hit_s[64];
char cert[2048];
char url[128];
struct sockaddr *lsi;
struct hip_conf *hc;
hc=malloc(sizeof(struct hip_conf));
memset(hc, 0, sizeof(struct hip_conf));
if(read_conf_file("hip.conf", hc)<0){
printf("cannot read hip.conf\n");
exit(-1);
}
host_p = (struct sockaddr*)&host_ss;
eb_p = (struct sockaddr*)&eb_ss;
char *dlname = "libhipcfg.so";
rc=hipcfg_init(dlname, hc);
if(rc<0){
printf("hipcfg_init failed.\n");
exit(-1);
}
hi_node *hi = hipcfg_getMyHostId();
if(hi == NULL)
printf("cannot get local host identity.\n");
else {
lsi = (struct sockaddr*)&hi->lsi;
inet_ntop(lsi->sa_family, SA2IP(lsi), host_s, sizeof(host_s));
hit2hitstr(hit_s, hi->hit);
printf("my host identity hit: %s lsi: %s name: %s\n", hit_s, host_s, hi->name);
}
strcpy(hit_s, "2001:1d:52a7:1633:48ae:b657:e975:9efa");
hitstr2hit(hit1, hit_s);
sprintf(url, "hit=%s,dc=endboxes,dc=sma,dc=boeing,dc=com", hit_s);
rc = hipcfg_verifyCert(url, hit1);
if (rc==1)
printf("certificate verified url %s\n", url);
else
printf("certificate not verified url %s\n", url);
strcpy(hit_s, "2001:1d:4e61:edab:ec2a:b310:201c:ffd0");
hitstr2hit(hit1, hit_s);
sprintf(url, "hit=%s,dc=endboxes,dc=sma,dc=boeing,dc=com", hit_s);
rc = hipcfg_verifyCert(url, hit1);
if (rc==1)
printf("certificate verified url %s\n", url);
else
printf("certificate not verified url %s\n", url);
//test cached cert that has been validated
strcpy(hit_s, "2001:1d:4e61:edab:ec2a:b310:201c:ffd0");
hitstr2hit(hit1, hit_s);
sprintf(url, "hit=%s,dc=endboxes,dc=sma,dc=boeing,dc=com", hit_s);
rc = hipcfg_verifyCert(url, hit1);
if (rc==1)
printf("certificate verified url %s - using cached cert\n", url);
else
printf("certificate not verified url %s - using cached cert\n", url);
strcpy(hit_s, "2001:1d:4e61:edab:ec2a:b310:201c:ffd0");
hitstr2hit(hit1, hit_s);
strcpy(hit_s, "2001:1d:52a7:1633:48ae:b657:e975:9efa");
hitstr2hit(hit2, hit_s);
rc=hipcfg_allowed_peers(hit1, hit2);
printf("hipcfg_allowed_peers positive case: returned %d\n", rc);
rc=hipcfg_allowed_peers(hit2, hit1);
printf("hipcfg_allowed_peers positive case: returned %d\n", rc);
hit1[0] = 0x99;
rc=hipcfg_allowed_peers(hit1, hit2);
printf("hipcfg_allowed_peers negative case: returned %d\n", rc);
hip_hit hits1[10], hits2[10];
rc = hipcfg_peers_allowed(hits1, hits2, 10);
if(rc>0){
for(i=0; i<rc; i++)
printf("peers_allowed: hit1 %02x%02x hit2 %02x%02x\n", *(hits1[i]+14), *(hits1[i]+15), *(hits2[i]+14), *(hits2[i]+15));
} else
printf("hipcfg_peers_allowed returned error\n");
strcpy(host_s, "192.168.0.15");
host_p->sa_family=AF_INET;
inet_pton(host_p->sa_family, host_s, SA2IP(host_p));
eb_p->sa_family=AF_INET;
rc=hipcfg_getEndboxByLegacyNode(host_p, eb_p);
inet_ntop(eb_p->sa_family, SA2IP(eb_p), eb_s, sizeof(eb_s));
printf("valid case hipcfg_getEndboxByLegacyNode, endbox in lsi, rc: %d host: %s eb: %s\n", rc, host_s, eb_s);
eb_p->sa_family=AF_INET6;
rc=hipcfg_getEndboxByLegacyNode(host_p, eb_p);
inet_ntop(eb_p->sa_family, SA2IP(eb_p), eb_s, sizeof(eb_s));
printf("valid case hipcfg_getEndboxByLegacyNode, endbox in hit, rc: %d host: %s eb: %s\n", rc, host_s, eb_s);
strcpy(host_s, "192.168.5.36");
host_p->sa_family=AF_INET;
inet_pton(AF_INET, host_s, SA2IP(host_p));
rc=hipcfg_getEndboxByLegacyNode(host_p, eb_p);
inet_ntop(eb_p->sa_family, SA2IP(eb_p), eb_s, sizeof(eb_s));
printf("invalid case hipcfg_getEndboxByLegacyNode rc: %d host: %s \n", rc, host_s);
strcpy(host_s, "1.117.158.250");
host_p->sa_family=AF_INET;
inet_pton(AF_INET, host_s, SA2IP(host_p));
eb_p->sa_family=AF_INET;
rc=hipcfg_getEndboxByLegacyNode(host_p, eb_p);
inet_ntop(eb_p->sa_family, SA2IP(eb_p), eb_s, sizeof(eb_s));
printf("valid case hipcfg_getEndboxByLegacyNode rc: %d host: %s eb: %s\n", rc, host_s, eb_s);
strcpy(eb_s, "2001:1d:52a7:1633:48ae:b657:e975:9efa");
eb_p->sa_family = AF_INET6;
inet_pton(eb_p->sa_family, eb_s, SA2IP(eb_p));
rc=hipcfg_getLlipByEndbox(eb_p, host_p);
inet_ntop(host_p->sa_family, SA2IP(host_p), host_s, sizeof(host_s));
printf("valid case hipcfg_getLlipByEndbox rc: %d endbox: %s bcwin: %s\n", rc, eb_s, host_s);
strcpy(eb_s, "1.117.158.250");
eb_p->sa_family=AF_INET;
inet_pton(AF_INET, eb_s, SA2IP(eb_p));
rc=hipcfg_getLegacyNodesByEndbox(eb_p, hosts, hosts_cnt);
if(rc>0){
printf("valid case hipcfg_getLegacyNodesByEndbox rc: %d legacyNodes for endbox %s: ", rc, eb_s);
for(i=0; i<rc; i++){
host_p = (struct sockaddr *)&hosts[i];
inet_ntop(host_p->sa_family, SA2IP(host_p), host_s, sizeof(host_s));
printf(" %s", host_s);
}
printf("\n");
} else
printf("hipcfg_getLegacyNodesByEndbox returned %d\n", rc);
struct peer_node nodes[10];
rc = hipcfg_getPeerNodes(nodes, 10);
if(rc < 0)
printf("error calling hipcfg_getPeerNodes\n");
else if (rc==0)
printf("no peer nodes found\n");
printf("hipcfg_getPeerNode returned %d entries\n", rc);
for(i=0; i<rc; i++){
hit2hitstr(hit_s, nodes[i].hit);
printf("peer node: hit: %s, assetTag: %s\n", hit_s, nodes[i].name);
}
if(hi==NULL)
exit(0); //no further test if not use smartcard
rc = hipcfg_getLocalCertUrl(url, sizeof(url));
if(rc==0)
printf("hipcfg_getLocalCertUrl succeed - url: %s\n", url);
else
printf("hipcfg_getLocalCertUrl returned error\n");
int fd = open("scCert.pem", O_RDONLY);
if(fd<0)
printf("error open scCert.pem\n");
else
rc = read(fd, cert, sizeof(cert));
if(fd < 0)
printf("error read scCert.pem\n");
BIO *bio_mem = BIO_new_mem_buf(cert, -1);
X509 *scCert=PEM_read_bio_X509(bio_mem, NULL, 0, NULL);
if (scCert==NULL)
{
printf("Error getting X509 certificate from PEM form\n");
exit(1);
}
EVP_PKEY *pubkey=X509_get_pubkey(scCert);
if(pubkey==NULL){
printf("error get public key from X509 cert.\n");
exit(1);
}
for (i=0; i<30; i++)
{
SHA_CTX c;
unsigned char md[SHA_DIGEST_LENGTH];
unsigned char rsa_sig[1024];
unsigned char data[512];
unsigned int sig_len;
SHA1_Init(&c);
SHA1_Update(&c, data, sizeof(data));
SHA1_Final(md, &c);
if(hi->rsa){
sig_len = RSA_size(hi->rsa);
rc=RSA_sign(NID_sha1, md, SHA_DIGEST_LENGTH, rsa_sig, &sig_len, hi->rsa);
if(rc!=1)
printf("RSA_sign failed\n");
else
printf("successfully signed a message digest.\n");
}
sig_len = RSA_size(hi->rsa);
rc=RSA_verify(NID_sha1, md, SHA_DIGEST_LENGTH, rsa_sig, sig_len, EVP_PKEY_get1_RSA(pubkey));
if(rc!=1)
printf("RSA_verify failed\n");
else
printf("RSA signature verified.\n");
}
return 0;
}

View File

@ -0,0 +1,304 @@
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
#include <netinet/in.h>
#include <netinet/ether.h>
#include <iostream>
#include <dlfcn.h>
#include <arpa/inet.h>
#include <hip/hip_cfg.h>
#define SA2IP(x) (((struct sockaddr*)x)->sa_family==AF_INET) ? \
(void *)&((struct sockaddr_in*)x)->sin_addr : \
(void *)&((struct sockaddr_in6*)x)->sin6_addr
#define SALEN(x) (((struct sockaddr*)x)->sa_family==AF_INET) ? \
sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6)
#define SAIPLEN(x) (((struct sockaddr*)x)->sa_family==AF_INET) ? 4 : 16
#define SA(x) ((struct sockaddr*)x)
int hipCfg::str_to_addr(const char *data, struct sockaddr *addr)
{
/* TODO: use platform-independent getaddrinfo() w/AI_NUMERICHOST */
#ifdef __WIN32__
int len = SALEN(addr);
return(WSAStringToAddress((LPSTR)data, addr->sa_family, NULL,
addr, &len)==0);
#else
return(inet_pton(addr->sa_family, (char*)data, SA2IP(addr)));
#endif
}
int hipCfg::addr_to_str(const struct sockaddr *addr, char *data, int len)
{
#ifdef __WIN32__
DWORD dw = (DWORD)len;
return(WSAAddressToString(addr, SALEN(addr), NULL, data, &dw)!=0);
#else
return(inet_ntop(addr->sa_family, SA2IP(addr), data, len)==NULL);
#endif
}
certInfo::~certInfo()
{
}
int hipCfg::hit2hitstr(char *hit_str, const hip_hit hit)
{
struct sockaddr *addr;
struct sockaddr_storage ss_addr;
addr = (struct sockaddr*) &ss_addr;
memset(&ss_addr, 0, sizeof(struct sockaddr_storage));
ss_addr.ss_family = AF_INET6;
memcpy(SA2IP(&ss_addr), hit, SAIPLEN(&ss_addr));
#ifdef __WIN32__
DWORD dw = (DWORD)INET6_ADDRSTRLEN;
return(WSAAddressToString(&ss_addr, SALEN(&ss_addr), NULL, hit_str, &dw)!=0);
#else
return(inet_ntop(addr->sa_family, SA2IP(addr), hit_str, INET6_ADDRSTRLEN)==NULL);
#endif
}
int hipCfg::hitstr2hit(hip_hit hit, char *hit_str)
{
struct sockaddr *addr;
struct sockaddr_storage ss_addr;
addr = (struct sockaddr*) &ss_addr;
if(strchr(hit_str, ':')){
memset(addr, 0,sizeof(struct sockaddr_storage));
addr->sa_family = AF_INET6;
if(str_to_addr(hit_str, addr) <= 0) {
cerr<<"invalid HIT value: "<<hit_str<<endl;
return -1;
}
memcpy(hit, SA2IP(addr), HIT_SIZE);
return 0;
}
return hex_to_bin(hit_str, (char *)hit, HIT_SIZE);
}
void hitPair::print() const
{
printf("hit1: %02x%02x, hit2: %02x%02x\n", _hit1[HIT_SIZE-2], _hit1[HIT_SIZE-1], _hit2[HIT_SIZE-2], _hit2[HIT_SIZE-1]);
}
int hipCfg::hit_peer_allowed(const hip_hit hit1, const hip_hit hit2)
{
int i;
set <hitPair>::iterator si;
hitPair *hpp;
/*
cout<<endl<<"hit_peer_allowed called with hit1: ";
for(i=0; i<sizeof(hip_hit); i++)
printf("%02x", hit1[i]);
cout<<" hit2: ";
for(i=0; i<sizeof(hip_hit); i++)
printf("%02x", hit2[i]);
cout<<endl;
*/
if(memcmp(hit1, hit2, HIT_SIZE) <0){
hpp = new hitPair(hit1, hit2);
} else if(memcmp(hit1, hit2, HIT_SIZE) >0) {
hpp= new hitPair(hit2, hit1);
} else
return 1;
si = _allowed_peers.find(*hpp);
if(si == _allowed_peers.end()){
delete hpp;
return 0;
}
delete hpp;
return 1;
}
int hipCfg::peers_allowed(hip_hit *hits1, hip_hit *hits2, int max_cnt)
{
set <hitPair, hp_compare>::iterator i;
int j;
for(j=0, i=_allowed_peers.begin(); i!=_allowed_peers.end(); i++, j++){
hitPair hp = *i;
if(j>=max_cnt)
return -1;
memcpy(hits1[j], hp._hit1, HIT_SIZE);
memcpy(hits2[j], hp._hit2, HIT_SIZE);
}
return j;
}
/* return 0 if the maping found, 1 otherwise */
int hipCfg::legacyNodeToEndbox(const struct sockaddr *host, struct sockaddr *eb)
{
char host_s[128];
string host_str;
string ip_s;
addr_to_str(host, host_s, 128);
//cout<<"legacyNodeToEndbox: look up host = "<<host_s<<endl;
host_str = host_s;
map <string, string>::iterator i;
i = _legacyNode2EndboxMap.find(host_str);
if(i != _legacyNode2EndboxMap.end()){
ip_s = (*i).second;
if(eb->sa_family!=AF_INET)
eb->sa_family = AF_INET6; //default to return HIT
if(eb->sa_family==AF_INET){
char lsi_s[INET_ADDRSTRLEN];
hitstr2lsistr(lsi_s, (char *)ip_s.c_str());
str_to_addr(lsi_s, eb);
} else
str_to_addr(ip_s.c_str(), eb);
//cout<<"legacyNodeToEndbox: get eb "<<ip_s.c_str()<<" for host = "<<host_s<<endl;
return 0;
}
return 1;
}
int hipCfg::getLegacyNodesByEndbox(const struct sockaddr *eb, struct sockaddr_storage *hosts, int size)
{
char eb_s[128];
char eb_lsi[INET_ADDRSTRLEN];
addr_to_str(eb, eb_s, 128);
int idx = 0;
map <string, string>::iterator i;
for(i=_legacyNode2EndboxMap.begin(); i!=_legacyNode2EndboxMap.end(); i++){
string host = (*i).first;
string endbox = (*i).second;
if(eb->sa_family==AF_INET){
hitstr2lsistr(eb_lsi, (char *)endbox.c_str());
endbox = eb_lsi;
}
if(endbox==eb_s && endbox != host) {
if(idx>=size) {
cout<<"error calling getLegacyNodesByEndbox: hosts array too small"<<endl;
return -1;
}
struct sockaddr_storage host_ss;
struct sockaddr *host_p = (struct sockaddr *)(&host_ss);
host_p->sa_family=AF_INET; //only handle IPv4 address only
str_to_addr(host.c_str(), host_p);
hosts[idx++] = host_ss;
}
}
return idx;
}
int hipCfg::endbox2Llip(const struct sockaddr *eb, struct sockaddr *llip)
{
char eb_s[INET6_ADDRSTRLEN];
string llip_s;
int rc;
memset(eb_s, 0, INET6_ADDRSTRLEN);
rc=addr_to_str(eb, eb_s, INET6_ADDRSTRLEN);
if(rc)
return -1;
//cout<<"endbox2Llip: look up bcwin for endbox = "<<eb_s<<endl;
map <string, string>::iterator i;
i = _endbox2LlipMap.find(eb_s);
if(i != _endbox2LlipMap.end()){
llip_s = (*i).second;
llip->sa_family=AF_INET; //only handle IPv4 address only
str_to_addr(llip_s.c_str(), llip);
//cout<<"endbox2Llip: get llip (bcwin) "<<llip_s.c_str()<<" for endbox = "<<eb_s<<endl;
return 0;
}
return 1;
}
/*
*
* hex_to_bin()
* in: src = input hex data
* dst = output binary data
* dst_len = requested number of binary bytes
* out: returns bytes converted if successful,
* -1 if error
*/
int hipCfg::hex_to_bin(char *src, char *dst, int dst_len)
{
char hex[] = "0123456789abcdef";
char hexcap[] = "0123456789ABCDEF";
char *p, c;
int src_len, total, i, val;
unsigned char o;
if ((!src) || (!dst))
return(-1);
src_len = strlen(src);
if (dst_len > src_len)
return(-1);
/* chop any '0x' prefix */
if ((src[0]=='0') && (src[1]=='x')) {
src += 2;
src_len -= 2;
}
/* convert requested number of bytes from hex to binary */
total = 0;
for (i=0; (i < src_len) && (total < dst_len) ; i+=2) {
/* most significant nibble */
c = src[i];
/*
* * Normally would use tolower(), but have found problems
* * with dynamic linking and different glibc versions
* */
if ((p = strchr(hex, c)) == NULL) {
if ((p = strchr(hexcap, c)) == NULL) {
continue;
}
val = p - hexcap;
} else {
val = p - hex;
}
if (val < 0 || val > 15) {
cerr<<"Binary conversion failed " <<c<<endl;
return(-1);
}
o = val << 4;
/* least significant nibble */
c = src[i+1];
if ((p = strchr(hex, c)) == NULL) {
if ((p = strchr(hexcap, c)) == NULL) {
continue;
}
val = p - hexcap;
} else {
val = p - hex;
}
if (val < 0 || val > 15) {
cerr<<"Binary conversion failed " << c <<endl;
return(-1);
}
o += val;
dst[total] = o;
total++;
if (total >= src_len)
total = dst_len;
}
return total;
}
#define HIT2LSI(a) ( 0x01000000L | \
((a[HIT_SIZE-3]<<16)+(a[HIT_SIZE-2]<<8)+(a[HIT_SIZE-1])))
int hipCfg::hitstr2lsistr(char *lsi_str, char *hit_str)
{
hip_hit hit;
hitstr2hit(hit, hit_str);
struct sockaddr_in lsi;
lsi.sin_family = AF_INET;
lsi.sin_addr.s_addr = ntohl(HIT2LSI(hit));
return addr_to_str(SA(&lsi), lsi_str, INET_ADDRSTRLEN);
}

View File

@ -0,0 +1,13 @@
INC=-I../../include -I/usr/include/libxml2
# -I/local/pkgs/opensc-0.9.6/include
all: libhipcfg.so.0
libhipcfg.so.0: ../cfg-common/hip_cfg.cpp hip_cfg_ldap.cpp
c++ ${INC} -c -MD -fPIC -g -Wall -Woverloaded-virtual -Wcast-qual ../cfg-common/hip_cfg.cpp hip_cfg_ldap.cpp
g++ -g -shared -Wl,-soname,libhipcfg.so.0 -o libhipcfg.so.0 hip_cfg_ldap.o hip_cfg.o -lc -lxml2 -L/usr/local/lib -lldapcpp -lldap -L/local/pkgs/opensc-0.9.6/lib -lopensc
ln -sf libhipcfg.so.0 libhipcfg.so
clean:
rm -f libhipcfg.so libhipcfg.so.0 hip_cfg.d hip_cfg_ldap.d
rm -f *.o

View File

@ -0,0 +1,232 @@
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
#include <netinet/in.h>
#include <netinet/ether.h>
#include <iostream>
#include <dlfcn.h>
#include <arpa/inet.h>
#include <hip/hip_cfg_ldap.h>
int hipCfg::str_to_addr(const char *data, struct sockaddr *addr)
{
/* TODO: use platform-independent getaddrinfo() w/AI_NUMERICHOST */
#ifdef __WIN32__
int len = SALEN(addr);
return(WSAStringToAddress((LPSTR)data, addr->sa_family, NULL,
addr, &len)==0);
#else
return(inet_pton(addr->sa_family, (char*)data, SA2IP(addr)));
#endif
}
int hipCfg::addr_to_str(const struct sockaddr *addr, char *data, int len)
{
#ifdef __WIN32__
DWORD dw = (DWORD)len;
return(WSAAddressToString(addr, SALEN(addr), NULL, data, &dw)!=0);
#else
return(inet_ntop(addr->sa_family, SA2IP(addr), data, len)==NULL);
#endif
}
hipCfg *hipCfg::_instance = NULL;
int hipCfg::hit2hitstr(char *hit_str, hip_hit hit)
{
struct sockaddr *addr;
struct sockaddr_storage ss_addr;
addr = (struct sockaddr*) &ss_addr;
memset(&ss_addr, 0, sizeof(struct sockaddr_storage));
ss_addr.ss_family = AF_INET6;
memcpy(SA2IP(&ss_addr), hit, SAIPLEN(&ss_addr));
#ifdef __WIN32__
DWORD dw = (DWORD)INET6_ADDRSTRLEN;
return(WSAAddressToString(&ss_addr, SALEN(&ss_addr), NULL, hit_str, &dw)!=0);
#else
return(inet_ntop(addr->sa_family, SA2IP(addr), hit_str, INET6_ADDRSTRLEN)==NULL);
#endif
}
int hipCfg::hitstr2hit(hip_hit hit, char *hit_str)
{
struct sockaddr *addr;
struct sockaddr_storage ss_addr;
addr = (struct sockaddr*) &ss_addr;
if(strchr(hit_str, ':')){
memset(addr, 0,sizeof(struct sockaddr_storage));
addr->sa_family = AF_INET6;
if(str_to_addr(hit_str, addr) <= 0) {
cerr<<"invalid HIT value: "<<hit_str<<endl;
return -1;
}
memcpy(hit, SA2IP(addr), HIT_SIZE);
return 0;
}
return hex_to_bin(hit_str, (char *)hit, HIT_SIZE);
}
int hipCfg::hit_peer_allowed(const hip_hit hit1, const hip_hit hit2)
{
/*
int i;
cout<<endl<<"hit_peer_allowed called with hit1: ";
for(i=0; i<sizeof(hip_hit); i++)
printf("%02x", hit1[i]);
cout<<" hit2: ";
for(i=0; i<sizeof(hip_hit); i++)
printf("%02x", hit2[i]);
cout<<endl;
*/
//allways return TRUE since overlay lookup implied ACL
return 1;
}
/* return 0 if the maping found, 1 otherwise */
int hipCfg::legacyNodeToEndbox(const struct sockaddr *host, struct sockaddr *eb)
{
char host_s[128];
string host_str;
string ip_s;
addr_to_str(host, host_s, 128);
//cout<<"legacyNodeToEndbox: look up host = "<<host_s<<endl;
host_str = host_s;
map <string, string>::iterator i;
i = _legacyNode2EndboxMap.find(host_str);
if(i != _legacyNode2EndboxMap.end()){
ip_s = (*i).second;
eb->sa_family=AF_INET; //only handle IPv4 address only
str_to_addr(ip_s.c_str(), eb);
//cout<<"legacyNodeToEndbox: get eb "<<ip_s.c_str()<<" for host = "<<host_s<<endl;
return 0;
}
return 1;
}
int hipCfg::getLegacyNodesByEndbox(const struct sockaddr *eb, struct sockaddr_storage *hosts, int size)
{
char eb_s[128];
addr_to_str(eb, eb_s, 128);
int idx = 0;
map <string, string>::iterator i;
for(i=_legacyNode2EndboxMap.begin(); i!=_legacyNode2EndboxMap.end(); i++){
string host = (*i).first;
string endbox = (*i).second;
if(endbox==eb_s && endbox != host) {
if(idx>=size) {
cout<<"error calling getLegacyNodesByEndbox: hosts array too small"<<endl;
return -1;
}
struct sockaddr_storage host_ss;
struct sockaddr *host_p = (struct sockaddr *)(&host_ss);
host_p->sa_family=AF_INET; //only handle IPv4 address only
str_to_addr(host.c_str(), host_p);
hosts[idx++] = host_ss;
}
}
return idx;
}
int hipCfg::endbox2Llip(const struct sockaddr *eb, struct sockaddr *llip)
{
char eb_s[128];
string llip_s;
addr_to_str(eb, eb_s, 128);
//cout<<"endbox2Llip: look up bcwin for endbox = "<<eb_s<<endl;
map <string, string>::iterator i;
i = _endbox2LlipMap.find(eb_s);
if(i != _endbox2LlipMap.end()){
llip_s = (*i).second;
llip->sa_family=AF_INET; //only handle IPv4 address only
str_to_addr(llip_s.c_str(), llip);
//cout<<"endbox2Llip: get llip (bcwin) "<<llip_s.c_str()<<" for endbox = "<<eb_s<<endl;
return 0;
}
return 1;
}
/*
*
* hex_to_bin()
* in: src = input hex data
* dst = output binary data
* dst_len = requested number of binary bytes
* out: returns bytes converted if successful,
* -1 if error
*/
int hipCfg::hex_to_bin(char *src, char *dst, int dst_len)
{
char hex[] = "0123456789abcdef";
char hexcap[] = "0123456789ABCDEF";
char *p, c;
int src_len, total, i, val;
unsigned char o;
if ((!src) || (!dst))
return(-1);
src_len = strlen(src);
if (dst_len > src_len)
return(-1);
/* chop any '0x' prefix */
if ((src[0]=='0') && (src[1]=='x')) {
src += 2;
src_len -= 2;
}
/* convert requested number of bytes from hex to binary */
total = 0;
for (i=0; (i < src_len) && (total < dst_len) ; i+=2) {
/* most significant nibble */
c = src[i];
/*
* * Normally would use tolower(), but have found problems
* * with dynamic linking and different glibc versions
* */
if ((p = strchr(hex, c)) == NULL) {
if ((p = strchr(hexcap, c)) == NULL) {
continue;
}
val = p - hexcap;
} else {
val = p - hex;
}
if (val < 0 || val > 15) {
cerr<<"Binary conversion failed " <<c<<endl;
return(-1);
}
o = val << 4;
/* least significant nibble */
c = src[i+1];
if ((p = strchr(hex, c)) == NULL) {
if ((p = strchr(hexcap, c)) == NULL) {
continue;
}
val = p - hexcap;
} else {
val = p - hex;
}
if (val < 0 || val > 15) {
cerr<<"Binary conversion failed " << c <<endl;
return(-1);
}
o += val;
dst[total] = o;
total++;
if (total >= src_len)
total = dst_len;
}
return total;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,18 @@
1. openldap-2.3.43.tar.gz - only contrib/ldapc++ is used for creating C++ libraries and header files.
and they are used for compiling hip ldap configuration DDL
2. install rpm packages for ldap server (tested on ebics):
db42-4.4.53
openslp-1.2.1
openldap2-2.3.32
3. install and configure ldap server
a. install the rpm packages in 2 in that order.
b. edit /etc/openldap/sldapd.conf
change lines: rootdn, suffix, rootpw
add line: "include IpLegacyNodes eq"
add line: "include /etc/openldap/schema/endbox.schema"
c. copy file endbox.schema to directory /etc/openldap/schema
d. run sldapindex
e. start sldap daemon: /etc/init.d/ldap start
f. run load-parents.sh" to load parent entries for endbox entries.
g. provision endbox entries as in example endboxes.ldif, OR
use ldapbrowser to provision it.

View File

@ -0,0 +1,58 @@
attributetype ( 1.3.6.1.1.1.9.20 NAME 'hit'
DESC 'Endbox HIT'
EQUALITY caseIgnoreIA5Match
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{64})
attributetype ( 1.3.6.1.1.1.9.21 NAME 'assetTag'
DESC 'Endbox assetTag embeded in smartcard'
EQUALITY caseIgnoreIA5Match
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{64} SINGLE-VALUE)
attributetype ( 1.3.6.1.1.1.9.22 NAME 'hostName'
DESC 'Endbox host name'
EQUALITY caseIgnoreIA5Match
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{64} SINGLE-VALUE)
attributetype ( 1.3.6.1.1.1.9.23 NAME 'lsi'
DESC 'Endbox LSI'
EQUALITY caseIgnoreIA5Match
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{64} SINGLE-VALUE)
attributetype ( 1.3.6.1.1.1.9.24 NAME 'underlayIp'
DESC 'IP Address of underlay network interface'
EQUALITY caseIgnoreIA5Match
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{64} SINGLE-VALUE)
attributetype ( 1.3.6.1.1.1.9.25 NAME 'legacyNodesIp'
DESC 'IP address of one or more Legacy nodes associated with an endbox'
EQUALITY caseIgnoreIA5Match
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{64})
attributetype ( 1.3.6.1.1.1.9.26 NAME 'cert'
DESC 'certificate in PEM format'
EQUALITY caseIgnoreIA5Match
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{2000} SINGLE-VALUE)
attributetype ( 1.3.6.1.1.1.9.27 NAME 'host1'
DESC 'one of a pair of nodes represented in hit or lsi'
EQUALITY caseIgnoreIA5Match
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{64})
attributetype ( 1.3.6.1.1.1.9.28 NAME 'host2'
DESC 'node hit or lsi'
EQUALITY caseIgnoreIA5Match
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{64})
# Object Class Definitions
objectclass ( 1.3.6.1.1.1.8.0 NAME 'endbox'
DESC 'endbox configuration data'
SUP top STRUCTURAL
MUST ( HIT)
MAY ( underLayIp $ lsi $ legacyNodesIp $hostName $ accessTag $ cert $ description ) )
objectclass ( 1.3.6.1.1.1.8.1 NAME 'peerAllowed'
DESC 'A pair of HIP nodes allowed to accecpt association with each other'
SUP top STRUCTURAL
MUST ( host1 $ host2 $ cn ))

View File

@ -0,0 +1,38 @@
dn: hit=2001:1d:4e61:edab:ec2a:b310:201c:ffd0, dc=endboxes, dc=sma, dc=boeing
, dc=com
lsi: 1.28.255.208
hostName: ebics
assetTag: ebics-1024
legacyNodesIp: 192.168.0.101
underlayIp: 130.42.64.199
objectClass: endbox
objectClass: top
description: AFT1
hit: 2001:1d:4e61:edab:ec2a:b310:201c:ffd0
dn: hit=2001:1b:3c01:38cb:ac9d:e7d5:79df:5110, dc=endboxes, dc=sma, dc=boeing
, dc=com
lsi: 1.223.81.16
hostName: ebaft1
assetTag: ebaft1-1024
legacyNodesIp: 192.168.0.14
legacyNodesIp: 192.168.0.15
description: ebaft1
objectClass: endbox
objectClass: top
underlayIp: 130.42.65.214
hit: 2001:1b:3c01:38cb:ac9d:e7d5:79df:5110
dn: hit=2001:15:5549:a1f:94c4:6233:a5e:ad4b, dc=endboxes, dc=sma, dc=boeing,
dc=com
lsi: 1.94.173.75
hostName: ebfwd1
assetTag: ebfwd1-1024
legacyNodesIp: 192.168.0.1
legacyNodesIp: 192.168.0.11
description: ebfwd1
objectClass: endbox
objectClass: top
underlayIp: 130.42.67.25
hit: 2001:15:5549:a1f:94c4:6233:a5e:ad4b

View File

@ -0,0 +1,38 @@
#!/bin/sh
ldapadd -x -c -D "cn=crawler,dc=sma,dc=boeing,dc=com" -w secret <<END
dn: dc=com
objectClass: top
objectClass: domain
dc: com
dn: dc=boeing,dc=com
objectClass: top
objectClass: domain
dc: boeing
dn: dc=sma,dc=boeing,dc=com
objectClass: top
objectClass: domain
dc: sma
dn: dc=endboxes,dc=sma,dc=boeing,dc=com
objectClass: top
objectClass: domain
dc: endboxes
dn: cn=crawler,dc=sma,dc=boeing,dc=com
objectClass: top
objectClass: person
sn: endboxes
cn: crawler
dn: dc=acl,dc=sma,dc=boeing,dc=com
objectClass: top
objectClass: domain
dc: acl
dn: dc=peerAllowed,dc=acl,dc=sma,dc=boeing,dc=com
objectClass: top
objectClass: domain
dc: peerAllowed
END

View File

@ -0,0 +1,2 @@
#!/bin/sh
ldapsearch -x -D "cn=crawler,dc=sma,dc=boeing,dc=com" -w secret -s sub -b "" "objectclass=*"

View File

@ -0,0 +1,2 @@
#!/bin/sh
ldapsearch -x -D "cn=crawler,dc=sma,dc=boeing,dc=com" -w secret -s onelevel -b "dc=endboxes,dc=sma,dc=boeing,dc=com" "objectclass=endbox"

View File

@ -0,0 +1,2 @@
#!/bin/sh
ldapsearch -x -D "cn=crawler,dc=sma,dc=boeing,dc=com" -w secret -s onelevel -b "dc=endboxes,dc=sma,dc=boeing,dc=com" "(&(objectclass=endbox)(EndboxLSI=1.22.213.190))"

View File

@ -0,0 +1,2 @@
#!/bin/sh
ldapsearch -x -D "cn=crawler,dc=sma,dc=boeing,dc=com" -w secret -s onelevel -b "dc=endboxes,dc=sma,dc=boeing,dc=com" "(&(objectclass=endbox)(IpLegacyNodes=192.168.0.101))" EndboxLSI IpEndboxBCWIN

367
src/util/checksum_test.c Normal file
View File

@ -0,0 +1,367 @@
/*
* Copyright (C) 2002-04 the Boeing Company
*
* 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 2 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.
*
* Checksum test program
*
* Tom Henderson (thomas.r.henderson@boeing.com)
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <asm/types.h>
#define HIP_OVER_UDP 0 /* set to 1 to use alternate HIP/UDP format */
#define IPV6 1 /* set HIP_OVER_UDP to 0 */
#define IPPROTO_NONE 59 /* used in HIP next header */
#define H_PROTO_HIP 99
#define HIP_I1 1
#define HIP_VERSION 1
#define IPV4_PSEUDO_SIZE 12 /* HIP is 12 bytes into IPv4 pseudo structure */
#define IPV6_PSEUDO_SIZE 40
#define HIT_SIZE 16
#define HIT_SNDR "0x40000000000000000000000000000001"
#define HIT_RCVR "0x40000000000000000000000000000002"
#define IPV4_SRC "0xc0000201" /* 192.0.2.1 */
#define IPV4_DST "0xc0000202" /* 192.0.2.2 */
/*
* IPv4 pseudoheader format
0 7 8 15 16 23 24 31
+--------+--------+--------+--------+
| source address |
+--------+--------+--------+--------+
| destination address |
+--------+--------+--------+--------+
| zero |protocol| length |
+--------+--------+--------+--------+
| |
/ /
| <transport layer header/data> |
\ \
| |
+--------+--------+--------+--------+
length is defined as the length of the
<transport layer header/data>; in this case,
it is the length of the whole HIP I1, in bytes
*/
/*
* IPv6 pseudoheader format
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
+ +
| |
+ Source Address +
| |
+ +
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
+ +
| |
+ Destination Address +
| |
+ +
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Upper-Layer Packet Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| zero | Next Header |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
The Upper-Layer Packet Length in the pseudo-header is the
length of the upper-layer header and data (e.g., TCP header
plus TCP data). Some upper-layer protocols carry their own
length information (e.g., the Length field in the UDP header);
for such protocols, that is the length used in the pseudo-
header. Other protocols (such as TCP) do not carry their own
length information, in which case the length used in the
pseudo-header is the Payload Length from the IPv6 header, minus
the length of any extension headers present between the IPv6
header and the upper-layer header.
*/
#if (IPV6)
typedef struct _pseudo_header
{
unsigned char src_addr[16];
unsigned char dst_addr[16];
__u32 packet_length;
char zero[3];
__u8 next_hdr;
} pseudo_header;
#else
typedef struct _pseudo_header
{
unsigned char src_addr[4];
unsigned char dst_addr[4];
__u8 zero;
__u8 protocol;
__u16 packet_length;
} pseudo_header;
#endif
typedef unsigned char hip_hit[16];
#if (HIP_OVER_UDP)
#define HIP_UDP_PORT 272
typedef struct _hiphdr {
__u16 src_port;
__u16 dst_port;
__u16 len;
__u16 checksum;
__u16 control; /* control */
__u8 packet_type; /* packet type */
__u8 res:4,version:4; /* version, reserved */
hip_hit hit_sndr; /* Sender's Host Identity Tag */
hip_hit hit_rcvr; /* Receiver's Host Identity Tag*/
/* HIP TLV parameters follow ... */
} hiphdr;
#else
typedef struct _hiphdr {
__u8 next_hdr; /* payload protocol */
__u8 payload_len; /* payload length */
__u8 packet_type; /* packet type */
__u8 res:4,version:4; /* version, reserved */
__u16 control; /* control */
__u16 checksum; /* checksum */
hip_hit hit_sndr; /* Sender's Host Identity Tag */
hip_hit hit_rcvr; /* Receiver's Host Identity Tag */
/* HIP TLV parameters follow ... */
} hiphdr;
#endif
static __u16 checksum_packet(char *, __u32, __u32);
static int hex_to_bin(char *, char *, int);
int main(int argc, char *argv[])
{
int i;
int checksummed_size;
hiphdr *hiph;
unsigned char buff[512];
hip_hit hit_sndr;
hip_hit hit_rcvr;
__u32 ip_src;
__u32 ip_dst;
char hit_sndr_char[] = HIT_SNDR;
char hit_rcvr_char[] = HIT_RCVR;
char ip_src_char[] = IPV4_SRC;
char ip_dst_char[] = IPV4_DST;
hex_to_bin(hit_sndr_char, hit_sndr, 16);
hex_to_bin(hit_rcvr_char, hit_rcvr, 16);
hex_to_bin(ip_src_char, (char*) &ip_src, 4);
hex_to_bin(ip_dst_char, (char*) &ip_dst, 4);
#if (HIP_OVER_UDP)
/* build the HIP header for I1*/
/* Leave 12 bytes for pseudoheader */
hiph = (hiphdr*) &buff[IPV4_PSEUDO_SIZE];
hiph->src_port = htons(HIP_UDP_PORT);
hiph->dst_port = htons(HIP_UDP_PORT);
hiph->len = htons(sizeof(hiphdr));
hiph->checksum = 0;
hiph->control = 0;
hiph->packet_type = HIP_I1;
hiph->version = HIP_VERSION;
hiph->res = 0;
#else
/* build the HIP header for I1*/
/* Leave 12 bytes up front for pseudoheader */
#if (IPV6)
hiph = (hiphdr*) &buff[IPV6_PSEUDO_SIZE];
#else
hiph = (hiphdr*) &buff[IPV4_PSEUDO_SIZE];
#endif
hiph->next_hdr = IPPROTO_NONE;
hiph->payload_len = 4; /* 2*sizeof(hip_hit)/8 */
hiph->packet_type = HIP_I1;
hiph->version = HIP_VERSION;
hiph->res = 0;
hiph->control = 0;
hiph->checksum = 0;
#endif
memcpy(hiph->hit_sndr, hit_sndr, HIT_SIZE);
memcpy(hiph->hit_rcvr, hit_rcvr, HIT_SIZE);
hiph->checksum = htons(checksum_packet(&buff[0], ip_src, ip_dst));
/* Print out results */
#if (HIP_OVER_UDP)
checksummed_size = sizeof(hiphdr) + IPV4_PSEUDO_SIZE;
printf("IPv4 UDP I1 with pseudoheader (first 12 bytes)");
#else
#if (IPV6)
checksummed_size = IPV6_PSEUDO_SIZE + ((hiph->payload_len + 1) * 8);
printf("IPv6 I1 with pseudoheader (first 40 bytes)");
#else
checksummed_size = IPV4_PSEUDO_SIZE + ((hiph->payload_len + 1) * 8);
printf("IPv4 I1 with pseudoheader (first 12 bytes)");
#endif
#endif
printf(" and corresponding checksum:\n\t");
for (i=0; i< checksummed_size; i++) {
if (i%4 == 0 && i != 0)
printf("\n\t");
printf("%02x", buff[i]);
}
printf("\n");
}
/*
* function checksum_packet()
*
* Calculates the checksum of a HIP packet with pseudo-header
* src and dst are assumed to be in network byte order already
* data is assumed to point to start of pseudoheader
*/
static
__u16 checksum_packet(char *data, __u32 src, __u32 dst)
{
__u16 checksum;
int length;
long sum = 0;
int count;
unsigned short *p; /* 16-bit */
hiphdr* hiph;
pseudo_header* pseudoh;
pseudoh = (pseudo_header*) &data[0];
hiph = (hiphdr*) &data[IPV4_PSEUDO_SIZE];
#if (IPV6)
hiph = (hiphdr*) &data[IPV6_PSEUDO_SIZE];
memset(pseudoh, 0, sizeof(pseudo_header));
memset(pseudoh->src_addr + 10, 0xFF, 2);
memset(pseudoh->dst_addr + 10, 0xFF, 2);
memcpy(pseudoh->src_addr + 12, &src, 4);
memcpy(pseudoh->dst_addr + 12, &dst, 4);
length = (hiph->payload_len + 1) * 8;
pseudoh->packet_length = htonl(length);
pseudoh->next_hdr = H_PROTO_HIP;
#else
hiph = (hiphdr*) &data[IPV4_PSEUDO_SIZE];
/* fill the IPv4-style pseudo-header (RFC 768)*/
memset(pseudoh, 0, sizeof(pseudo_header));
memcpy(pseudoh->src_addr, &src, 4);
memcpy(pseudoh->dst_addr, &dst, 4);
pseudoh->protocol = H_PROTO_HIP;
#if (HIP_OVER_UDP)
length = ntohs(hiph->len);
pseudoh->packet_length = hiph->len; /* Already in network order */
#else
length = (hiph->payload_len + 1) * 8;
pseudoh->packet_length = htons(length);
#endif
#endif
/*
* this checksum algorithm can be found
* in RFC 1071 section 4.1
*/
/* one's complement sum 16-bit words of data */
#if (IPV6)
count = length + IPV6_PSEUDO_SIZE;
#else
count = length + IPV4_PSEUDO_SIZE;
#endif
p = (unsigned short*) data;
while (count > 1) {
sum += *p++;
count -= 2;
}
/* add left-over byte, if any */
if (count > 0)
sum += (unsigned char)*p;
/* Fold 32-bit sum to 16 bits */
while (sum>>16)
sum = (sum & 0xffff) + (sum >> 16);
/* take the one's complement of the sum */
checksum = ~sum;
return checksum;
}
/*
* Convert character string found in src to binary dst
* - leaves in network byte order
*/
static
int hex_to_bin(char *src, char *dst, int dst_len)
{
char hex[] = "0123456789abcdef";
char hexcap[] = "0123456789ABCDEF";
char *p, c;
int src_len, total, i;
unsigned char o;
if ((!src) || (!dst))
return(-1);
src_len = strlen(src);
if (dst_len > src_len)
return(-1);
/* chop any '0x' prefix */
if ((src[0]=='0') && (src[1]=='x')) {
src += 2;
src_len -= 2;
}
/* convert requested number of bytes from hex to binary */
total = 0;
for (i=0; (i < src_len) && (total < dst_len) ; i+=2) {
/* most significant nibble */
c = src[i];
/*
* Normally would use tolower(), but have found problems
* with dynamic linking and different glibc versions
*/
if ((p = strchr(hex, c)) == NULL) {
if ((p = strchr(hexcap, c)) == NULL) {
continue;
}
}
if ((p-hex) < 0 || (p-hex) > 15) {
fprintf(stderr, "Binary conversion failed %c\n",c);
return(-1);
}
o = (p - hex) << 4;
/* least significant nibble */
c = src[i+1];
if ((p = strchr(hex, c)) == NULL) {
if ((p = strchr(hexcap, c)) == NULL) {
continue;
}
}
if ((p-hex) < 0 || (p-hex) > 15) {
fprintf(stderr, "Binary conversion failed 2 %c", c);
return(-1);
}
o += (p - hex);
dst[total] = o;
total++;
if (total >= src_len)
total = dst_len;
}
return total;
}

Some files were not shown because too many files have changed in this diff Show More