Import sipsak 0.9.6 from upstream.

Change T1 timer from 500ms to 150ms during compile time.
Abort after exceeding T1 * value of cmd switch "-D" instead of after 32sec.

This results in much more responsive monitoring in case of service failures.
remotes/svn/0.9.6 0.9.6+sipwise1
Andreas Granig 14 years ago
commit 6b83a5e58e

@ -0,0 +1,22 @@
# $Id: AUTHORS 397 2006-01-28 21:11:50Z calrissian $
# The format of this file was inspired by the Linux kernel CREDITS file.
#
# Authors and contributors are listed alphabetically (first name).
#
# The fields are: name (N), email (E), web-address (W), CVS account login (C),
# PGP key ID and fingerprint (P), description (D), and snail-mail address (S).
N: Nils Ohlmeier
C: calrissian
E: nils@sipsak.org
W: http://www.ohlmeier.org
P: BAD6CA40 B5E7 4FB0 800F 0A2C E3E9 4073 C7C3 F275 BAD6 CA40
D: the original author and main developer
N: Jan Janak
E: jan@iptel.org
D: contributed for example the forking code and several ideas
N: Jiri Kuthan
E: jiri@iptel.org
D: contributed the exit code code and uncounted bug reports and ideas

@ -0,0 +1,340 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 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 Library 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 Library General
Public License instead of this License.

@ -0,0 +1,111 @@
* version 0.9.6
- added new option -j to add a header
- added support for multiple variable replacement (option -g)
- added support for reading password from stdin
- added support for SHA1 as digest algorithm for authentication
- added supoprt for multiple test runs to calculate avarage timming values
- fixed support for cygwin
- fixed using wrong interface and symmetric signaling when running as root
- fixed mem leak when using ares
* version 0.9.5
- added support for TCP transport
- added new option -E to specify the transport
- renamed --invite-timeout to --timeout-after
- added support for c-ares for DNS SRV lookups (http://daniel.haxx.se/projects/c-ares/)
- improved lib ruli detection
- openssl detection is only done when gnutls is missing
- added username to flood mode
- fixed millisecond sleep (thanks to Juri Glass)
- fixed variable replacing (thanks to Todd Ingarfield)
- fixed MD5 detection and compilation
- re-enabled compilation and usage for CygWin
* version 0.9.2
- added new option -D to specify maximum INVITE timeout value
- option -c takes From header for MESSAGE's
- added support for gnutls, which is prefered over openssl now
see configure options --disable-gnutls and --with-libgnutls-prefix
- fixed compilation for Solaris
- fixed ACK building
- fixed several issues with ports and usernames in ruri and outbound proxy
- fixed mis-interpretation of ICMP error messages
- fixed wrong port from SRV entry
- fixed sipsk was still case-sensitive allthough strcasecmp was available
* version 0.9.1
- added RFC compliant retransmissons of INVITE requests
- fixed compilation errors for BSD and MacOSX
- ACK creation will be rejected for strict routing
- removed obsoleted options from configure
* version 0.9.0
- added new option -S to allow symmetrical signaling in non-root mode
- the option -z now takes an percent argument for the likeliness of binding
removale
- Via contains now branch with magic cookie
- INVITE replies will be answered with ACKs automatically
- basic support for Record-Route and loose routing (strict routing is not
supported yet)
- if an outbound proxy was given it will even be used after being redirected
- request source and destiantion will be printed by -vvv
- the read in file will be checked for conatining an empty line as body
separator
- fixed wrong checking for getopt header in configure
- usage of global functions for memory allocation and integer convertion
- seperated the code into several small functions to make it easier
understandable and better mantainable for the future
* version 0.8.13
- nonce count contains the required leading zeros now
- content length is printed as integer and not as hex value
- DNS SRV lookup support through libruli (for target URI, outbound proxy and
redirects)
- all comparisons are now case in-sensitiv if suport by the system
- destination port can be given in the outbound proxy argument
* version 0.8.12
- Nagios compliant return codes (-N)
- use strcasestr if available for case-insensitive compareings
- ACK will be send for 40[17] replies on INVITE
- just return the timing values of the operation (-A)
- relaxed Contact check of option -C
- numeric (-n) is now on by default
* version 0.8.11
- try authentication with empty password instead of username if no
password is given
- support to read SIP message from standard input (-f -)
- insert missing CR in front of LF (-L)
- use different username for authentication (-u)
- use multiple processes for usrloc, message and invite mode (-P)
- search for a string in the reply with a regular expression (-q)
* version 0.8.10
- send instant messages (just -M)
- RFC 3261 compliant retransmission timer
- added From (and To) tags
- use MD5 from openssl if available
- new argument -C to use any given contact value, even empty
- support long options if available
- support Nagios warn level with optional numbers of retransmissions
- use a raw socket if available to support broken RFC 3581 implementations
- small fixes and betaufications
* version 0.8.9
- added Nagios compliant exit codes
- fixed missing replies from un-symmetric servers
- added outbound proxy option
- fixed SIP issues (CSeq increasement on authorization and added missing To and From tags)
* version 0.8.8
- added -p option to use an outbound proxy
- added -C option to use given Contact in REGISTER
- fixed authentication failure when password given as last option
* version 0.8.7
- merged listening and sending socket into one
- added rport parameter to all Via lines
- improved error reporting on host name resolving problems
* version 0.8.6
- fixed wrong number of retries and timeouts from configure
- fixed missing username in default mode
* version 0.8.5
- seperated code into several files
- introduced autoconf & automake
- added option -o for sleeping between requests
- added option -H to overwrite automatic hostname detection
- ignores provisional responses in usrloc mode
- added support for proxy authorization (407)
- fixed missing port from uri in requests
- number of retrys is configure option
- maximum timeout value is configure option

@ -0,0 +1,229 @@
Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002 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=PATH'.
You can specify separate installation prefixes for
architecture-specific files and architecture-independent files. If you
give `configure' the option `--exec-prefix=PATH', the package will use
PATH 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=PATH' 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
will cause the specified gcc to be used as the C compiler (unless it is
overridden in the site shell script).
`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.

@ -0,0 +1,5 @@
CC = ${DISTCC} @CC@
bin_PROGRAMS=sipsak
sipsak_SOURCES=auth.c auth.h header_f.c header_f.h helper.c helper.h md5.c md5.h md5global.h request.c request.h shoot.c shoot.h sipsak.c sipsak.h exit_code.h exit_code.c transport.c transport.h
dist_man1_MANS=sipsak.1

@ -0,0 +1,711 @@
# Makefile.in generated by automake 1.11 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
# Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
@SET_MAKE@
VPATH = @srcdir@
pkgdatadir = $(datadir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkglibexecdir = $(libexecdir)/@PACKAGE@
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_HEADER = $(INSTALL_DATA)
transform = $(program_transform_name)
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
bin_PROGRAMS = sipsak$(EXEEXT)
subdir = .
DIST_COMMON = README $(am__configure_deps) $(dist_man1_MANS) \
$(srcdir)/Makefile.am $(srcdir)/Makefile.in \
$(srcdir)/config.h.in $(top_srcdir)/configure AUTHORS COPYING \
ChangeLog INSTALL NEWS TODO config.guess config.sub depcomp \
install-sh missing mkinstalldirs
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
$(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
configure.lineno config.status.lineno
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
CONFIG_HEADER = config.h
CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)"
PROGRAMS = $(bin_PROGRAMS)
am_sipsak_OBJECTS = auth.$(OBJEXT) header_f.$(OBJEXT) helper.$(OBJEXT) \
md5.$(OBJEXT) request.$(OBJEXT) shoot.$(OBJEXT) \
sipsak.$(OBJEXT) exit_code.$(OBJEXT) transport.$(OBJEXT)
sipsak_OBJECTS = $(am_sipsak_OBJECTS)
sipsak_LDADD = $(LDADD)
DEFAULT_INCLUDES = -I.@am__isrc@
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
CCLD = $(CC)
LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
SOURCES = $(sipsak_SOURCES)
DIST_SOURCES = $(sipsak_SOURCES)
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
am__vpath_adj = case $$p in \
$(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
*) f=$$p;; \
esac;
am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
am__install_max = 40
am__nobase_strip_setup = \
srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
am__nobase_strip = \
for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
am__nobase_list = $(am__nobase_strip_setup); \
for p in $$list; do echo "$$p $$p"; done | \
sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
$(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
if (++n[$$2] == $(am__install_max)) \
{ print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
END { for (dir in files) print dir, files[dir] }'
am__base_list = \
sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
man1dir = $(mandir)/man1
NROFF = nroff
MANS = $(dist_man1_MANS)
ETAGS = etags
CTAGS = ctags
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
distdir = $(PACKAGE)-$(VERSION)
top_distdir = $(distdir)
am__remove_distdir = \
{ test ! -d "$(distdir)" \
|| { find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \
&& rm -fr "$(distdir)"; }; }
DIST_ARCHIVES = $(distdir).tar.gz
GZIP_ENV = --best
distuninstallcheck_listfiles = find . -type f -print
distcleancheck_listfiles = find . -type f -print
ACLOCAL = @ACLOCAL@
AMTAR = @AMTAR@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
CC = ${DISTCC} @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
DISTCC = @DISTCC@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
GREP = @GREP@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LDFLAGS = @LDFLAGS@
LIBGNUTLS_CFLAGS = @LIBGNUTLS_CFLAGS@
LIBGNUTLS_LIBS = @LIBGNUTLS_LIBS@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LTLIBOBJS = @LTLIBOBJS@
MAINT = @MAINT@
MAKEINFO = @MAKEINFO@
MKDIR_P = @MKDIR_P@
OBJEXT = @OBJEXT@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_STRING = @PACKAGE_STRING@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
PKG_CONFIG = @PKG_CONFIG@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
SIPSAK_HAVE_ARES = @SIPSAK_HAVE_ARES@
STRIP = @STRIP@
VERSION = @VERSION@
abs_builddir = @abs_builddir@
abs_srcdir = @abs_srcdir@
abs_top_builddir = @abs_top_builddir@
abs_top_srcdir = @abs_top_srcdir@
ac_ct_CC = @ac_ct_CC@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
am__tar = @am__tar@
am__untar = @am__untar@
bindir = @bindir@
build = @build@
build_alias = @build_alias@
build_cpu = @build_cpu@
build_os = @build_os@
build_vendor = @build_vendor@
builddir = @builddir@
datadir = @datadir@
datarootdir = @datarootdir@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
host = @host@
host_alias = @host_alias@
host_cpu = @host_cpu@
host_os = @host_os@
host_vendor = @host_vendor@
htmldir = @htmldir@
includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
libdir = @libdir@
libexecdir = @libexecdir@
localedir = @localedir@
localstatedir = @localstatedir@
mandir = @mandir@
mkdir_p = @mkdir_p@
oldincludedir = @oldincludedir@
pdfdir = @pdfdir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
sysconfdir = @sysconfdir@
target_alias = @target_alias@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
sipsak_SOURCES = auth.c auth.h header_f.c header_f.h helper.c helper.h md5.c md5.h md5global.h request.c request.h shoot.c shoot.h sipsak.c sipsak.h exit_code.h exit_code.c transport.c transport.h
dist_man1_MANS = sipsak.1
all: config.h
$(MAKE) $(AM_MAKEFLAGS) all-am
.SUFFIXES:
.SUFFIXES: .c .o .obj
am--refresh:
@:
$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
@for dep in $?; do \
case '$(am__configure_deps)' in \
*$$dep*) \
echo ' cd $(srcdir) && $(AUTOMAKE) --gnu'; \
$(am__cd) $(srcdir) && $(AUTOMAKE) --gnu \
&& exit 0; \
exit 1;; \
esac; \
done; \
echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu Makefile'; \
$(am__cd) $(top_srcdir) && \
$(AUTOMAKE) --gnu Makefile
.PRECIOUS: Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
*config.status*) \
echo ' $(SHELL) ./config.status'; \
$(SHELL) ./config.status;; \
*) \
echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \
cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \
esac;
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
$(SHELL) ./config.status --recheck
$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
$(am__cd) $(srcdir) && $(AUTOCONF)
$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
$(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS)
$(am__aclocal_m4_deps):
config.h: stamp-h1
@if test ! -f $@; then \
rm -f stamp-h1; \
$(MAKE) $(AM_MAKEFLAGS) stamp-h1; \
else :; fi
stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status
@rm -f stamp-h1
cd $(top_builddir) && $(SHELL) ./config.status config.h
$(srcdir)/config.h.in: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
($(am__cd) $(top_srcdir) && $(AUTOHEADER))
rm -f stamp-h1
touch $@
distclean-hdr:
-rm -f config.h stamp-h1
install-binPROGRAMS: $(bin_PROGRAMS)
@$(NORMAL_INSTALL)
test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)"
@list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
for p in $$list; do echo "$$p $$p"; done | \
sed 's/$(EXEEXT)$$//' | \
while read p p1; do if test -f $$p; \
then echo "$$p"; echo "$$p"; else :; fi; \
done | \
sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \
-e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
sed 'N;N;N;s,\n, ,g' | \
$(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
{ d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
if ($$2 == $$4) files[d] = files[d] " " $$1; \
else { print "f", $$3 "/" $$4, $$1; } } \
END { for (d in files) print "f", d, files[d] }' | \
while read type dir files; do \
if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
test -z "$$files" || { \
echo " $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \
$(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \
} \
; done
uninstall-binPROGRAMS:
@$(NORMAL_UNINSTALL)
@list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
files=`for p in $$list; do echo "$$p"; done | \
sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
-e 's/$$/$(EXEEXT)/' `; \
test -n "$$list" || exit 0; \
echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \
cd "$(DESTDIR)$(bindir)" && rm -f $$files
clean-binPROGRAMS:
-test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
sipsak$(EXEEXT): $(sipsak_OBJECTS) $(sipsak_DEPENDENCIES)
@rm -f sipsak$(EXEEXT)
$(LINK) $(sipsak_OBJECTS) $(sipsak_LDADD) $(LIBS)
mostlyclean-compile:
-rm -f *.$(OBJEXT)
distclean-compile:
-rm -f *.tab.c
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/auth.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/exit_code.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/header_f.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/helper.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/md5.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/request.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/shoot.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sipsak.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/transport.Po@am__quote@
.c.o:
@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(COMPILE) -c $<
.c.obj:
@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
install-man1: $(dist_man1_MANS)
@$(NORMAL_INSTALL)
test -z "$(man1dir)" || $(MKDIR_P) "$(DESTDIR)$(man1dir)"
@list='$(dist_man1_MANS)'; test -n "$(man1dir)" || exit 0; \
{ for i in $$list; do echo "$$i"; done; \
} | while read p; do \
if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
echo "$$d$$p"; echo "$$p"; \
done | \
sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \
-e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \
sed 'N;N;s,\n, ,g' | { \
list=; while read file base inst; do \
if test "$$base" = "$$inst"; then list="$$list $$file"; else \
echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man1dir)/$$inst'"; \
$(INSTALL_DATA) "$$file" "$(DESTDIR)$(man1dir)/$$inst" || exit $$?; \
fi; \
done; \
for i in $$list; do echo "$$i"; done | $(am__base_list) | \
while read files; do \
test -z "$$files" || { \
echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man1dir)'"; \
$(INSTALL_DATA) $$files "$(DESTDIR)$(man1dir)" || exit $$?; }; \
done; }
uninstall-man1:
@$(NORMAL_UNINSTALL)
@list='$(dist_man1_MANS)'; test -n "$(man1dir)" || exit 0; \
files=`{ for i in $$list; do echo "$$i"; done; \
} | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \
-e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \
test -z "$$files" || { \
echo " ( cd '$(DESTDIR)$(man1dir)' && rm -f" $$files ")"; \
cd "$(DESTDIR)$(man1dir)" && rm -f $$files; }
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in files) print i; }; }'`; \
mkid -fID $$unique
tags: TAGS
TAGS: $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
set x; \
here=`pwd`; \
list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in files) print i; }; }'`; \
shift; \
if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
test -n "$$unique" || unique=$$empty_fix; \
if test $$# -gt 0; then \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
"$$@" $$unique; \
else \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
$$unique; \
fi; \
fi
ctags: CTAGS
CTAGS: $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in files) print i; }; }'`; \
test -z "$(CTAGS_ARGS)$$unique" \
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
$$unique
GTAGS:
here=`$(am__cd) $(top_builddir) && pwd` \
&& $(am__cd) $(top_srcdir) \
&& gtags -i $(GTAGS_ARGS) "$$here"
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
distdir: $(DISTFILES)
@list='$(MANS)'; if test -n "$$list"; then \
list=`for p in $$list; do \
if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
if test -f "$$d$$p"; then echo "$$d$$p"; else :; fi; done`; \
if test -n "$$list" && \
grep 'ab help2man is required to generate this page' $$list >/dev/null; then \
echo "error: found man pages containing the \`missing help2man' replacement text:" >&2; \
grep -l 'ab help2man is required to generate this page' $$list | sed 's/^/ /' >&2; \
echo " to fix them, install help2man, remove and regenerate the man pages;" >&2; \
echo " typically \`make maintainer-clean' will remove them" >&2; \
exit 1; \
else :; fi; \
else :; fi
$(am__remove_distdir)
test -d "$(distdir)" || mkdir "$(distdir)"
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
list='$(DISTFILES)'; \
dist_files=`for file in $$list; do echo $$file; done | \
sed -e "s|^$$srcdirstrip/||;t" \
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
case $$dist_files in \
*/*) $(MKDIR_P) `echo "$$dist_files" | \
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
sort -u` ;; \
esac; \
for file in $$dist_files; do \
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
if test -d $$d/$$file; then \
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
if test -d "$(distdir)/$$file"; then \
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
fi; \
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
fi; \
cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
else \
test -f "$(distdir)/$$file" \
|| cp -p $$d/$$file "$(distdir)/$$file" \
|| exit 1; \
fi; \
done
-test -n "$(am__skip_mode_fix)" \
|| find "$(distdir)" -type d ! -perm -777 -exec chmod a+rwx {} \; -o \
! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \
! -type d ! -perm -400 -exec chmod a+r {} \; -o \
! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \
|| chmod -R a+r "$(distdir)"
dist-gzip: distdir
tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
$(am__remove_distdir)
dist-bzip2: distdir
tardir=$(distdir) && $(am__tar) | bzip2 -9 -c >$(distdir).tar.bz2
$(am__remove_distdir)
dist-lzma: distdir
tardir=$(distdir) && $(am__tar) | lzma -9 -c >$(distdir).tar.lzma
$(am__remove_distdir)
dist-xz: distdir
tardir=$(distdir) && $(am__tar) | xz -c >$(distdir).tar.xz
$(am__remove_distdir)
dist-tarZ: distdir
tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z
$(am__remove_distdir)
dist-shar: distdir
shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz
$(am__remove_distdir)
dist-zip: distdir
-rm -f $(distdir).zip
zip -rq $(distdir).zip $(distdir)
$(am__remove_distdir)
dist dist-all: distdir
tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
$(am__remove_distdir)
# This target untars the dist file and tries a VPATH configuration. Then
# it guarantees that the distribution is self-contained by making another
# tarfile.
distcheck: dist
case '$(DIST_ARCHIVES)' in \
*.tar.gz*) \
GZIP=$(GZIP_ENV) gunzip -c $(distdir).tar.gz | $(am__untar) ;;\
*.tar.bz2*) \
bunzip2 -c $(distdir).tar.bz2 | $(am__untar) ;;\
*.tar.lzma*) \
unlzma -c $(distdir).tar.lzma | $(am__untar) ;;\
*.tar.xz*) \
xz -dc $(distdir).tar.xz | $(am__untar) ;;\
*.tar.Z*) \
uncompress -c $(distdir).tar.Z | $(am__untar) ;;\
*.shar.gz*) \
GZIP=$(GZIP_ENV) gunzip -c $(distdir).shar.gz | unshar ;;\
*.zip*) \
unzip $(distdir).zip ;;\
esac
chmod -R a-w $(distdir); chmod a+w $(distdir)
mkdir $(distdir)/_build
mkdir $(distdir)/_inst
chmod a-w $(distdir)
test -d $(distdir)/_build || exit 0; \
dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \
&& dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \
&& am__cwd=`pwd` \
&& $(am__cd) $(distdir)/_build \
&& ../configure --srcdir=.. --prefix="$$dc_install_base" \
$(DISTCHECK_CONFIGURE_FLAGS) \
&& $(MAKE) $(AM_MAKEFLAGS) \
&& $(MAKE) $(AM_MAKEFLAGS) dvi \
&& $(MAKE) $(AM_MAKEFLAGS) check \
&& $(MAKE) $(AM_MAKEFLAGS) install \
&& $(MAKE) $(AM_MAKEFLAGS) installcheck \
&& $(MAKE) $(AM_MAKEFLAGS) uninstall \
&& $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \
distuninstallcheck \
&& chmod -R a-w "$$dc_install_base" \
&& ({ \
(cd ../.. && umask 077 && mkdir "$$dc_destdir") \
&& $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \
&& $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \
&& $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \
distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \
} || { rm -rf "$$dc_destdir"; exit 1; }) \
&& rm -rf "$$dc_destdir" \
&& $(MAKE) $(AM_MAKEFLAGS) dist \
&& rm -rf $(DIST_ARCHIVES) \
&& $(MAKE) $(AM_MAKEFLAGS) distcleancheck \
&& cd "$$am__cwd" \
|| exit 1
$(am__remove_distdir)
@(echo "$(distdir) archives ready for distribution: "; \
list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \
sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x'
distuninstallcheck:
@$(am__cd) '$(distuninstallcheck_dir)' \
&& test `$(distuninstallcheck_listfiles) | wc -l` -le 1 \
|| { echo "ERROR: files left after uninstall:" ; \
if test -n "$(DESTDIR)"; then \
echo " (check DESTDIR support)"; \
fi ; \
$(distuninstallcheck_listfiles) ; \
exit 1; } >&2
distcleancheck: distclean
@if test '$(srcdir)' = . ; then \
echo "ERROR: distcleancheck can only run from a VPATH build" ; \
exit 1 ; \
fi
@test `$(distcleancheck_listfiles) | wc -l` -eq 0 \
|| { echo "ERROR: files left in build directory after distclean:" ; \
$(distcleancheck_listfiles) ; \
exit 1; } >&2
check-am: all-am
check: check-am
all-am: Makefile $(PROGRAMS) $(MANS) config.h
installdirs:
for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)"; do \
test -z "$$dir" || $(MKDIR_P) "$$dir"; \
done
install: install-am
install-exec: install-exec-am
install-data: install-data-am
uninstall: uninstall-am
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
installcheck: installcheck-am
install-strip:
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
`test -z '$(STRIP)' || \
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
mostlyclean-generic:
clean-generic:
distclean-generic:
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
clean: clean-am
clean-am: clean-binPROGRAMS clean-generic mostlyclean-am
distclean: distclean-am
-rm -f $(am__CONFIG_DISTCLEAN_FILES)
-rm -rf ./$(DEPDIR)
-rm -f Makefile
distclean-am: clean-am distclean-compile distclean-generic \
distclean-hdr distclean-tags
dvi: dvi-am
dvi-am:
html: html-am
html-am:
info: info-am
info-am:
install-data-am: install-man
install-dvi: install-dvi-am
install-dvi-am:
install-exec-am: install-binPROGRAMS
install-html: install-html-am
install-html-am:
install-info: install-info-am
install-info-am:
install-man: install-man1
install-pdf: install-pdf-am
install-pdf-am:
install-ps: install-ps-am
install-ps-am:
installcheck-am:
maintainer-clean: maintainer-clean-am
-rm -f $(am__CONFIG_DISTCLEAN_FILES)
-rm -rf $(top_srcdir)/autom4te.cache
-rm -rf ./$(DEPDIR)
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
mostlyclean: mostlyclean-am
mostlyclean-am: mostlyclean-compile mostlyclean-generic
pdf: pdf-am
pdf-am:
ps: ps-am
ps-am:
uninstall-am: uninstall-binPROGRAMS uninstall-man
uninstall-man: uninstall-man1
.MAKE: all install-am install-strip
.PHONY: CTAGS GTAGS all all-am am--refresh check check-am clean \
clean-binPROGRAMS clean-generic ctags dist dist-all dist-bzip2 \
dist-gzip dist-lzma dist-shar dist-tarZ dist-xz dist-zip \
distcheck distclean distclean-compile distclean-generic \
distclean-hdr distclean-tags distcleancheck distdir \
distuninstallcheck dvi dvi-am html html-am info info-am \
install install-am install-binPROGRAMS install-data \
install-data-am install-dvi install-dvi-am install-exec \
install-exec-am install-html install-html-am install-info \
install-info-am install-man install-man1 install-pdf \
install-pdf-am install-ps install-ps-am install-strip \
installcheck installcheck-am installdirs maintainer-clean \
maintainer-clean-generic mostlyclean mostlyclean-compile \
mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \
uninstall-am uninstall-binPROGRAMS uninstall-man \
uninstall-man1
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:

39
NEWS

@ -0,0 +1,39 @@
* version 0.9.6
- added new option -j to add a header
- added support for multiple variable replacement (option -g)
- added support for SHA1 as digest algorithm for authentication
* version 0.9.5
- renamed --invite-timeout to --timeout-factor
- new option -E specifies the transport (UDP or TCP)
- SRV lookup via c-ares is available
(http://daniel.haxx.se/projects/c-ares/)
* version 0.9.2
- prefers gnutls over openssl now
- new option -D specifies the maximum INVITE timeout value
- option -c specifies From header for MESSAGEs
* version 0.9.1
- only fixes, no new options or features
* version 0.9.0
- option -c in flood mode is replaced be -e
* version 0.8.13
- SRV lookup is supported if libruli is available
(http://www.nongnu.org/ruli/)
* version 0.8.12
- numeric (-n) is now on by default
* version 0.8.11
- try authentication with empty password instead of username if no
password is given
- support to read SIP message from standard input (-f -)
* version 0.8.10
- send instant messages (just -M)
- new argument -C to use any given contact value, even empty
- support long options if available
- support Nagios warn level with optional numbers of retransmissions
* version 0.8.6
- important fixes
* version 0.8.5
- ignores provisional responses in usrloc mode (-U)
- added support for proxy authorization (407)
- new argument -H overwrites automatic hostname detection
- new argument -o introduces sleeping seconds before sending next request
- number of retrys and maximum timeout values are configure options

@ -0,0 +1,49 @@
REQUIREMENTS
============
None.
Optional:
- Have
GnuTLS (http://www.gnutls.org/)
or
OpenSSL (http://www.openssl.org/)
installed on your system to use their MD5 implementations
instead of sipsak own version.
- Have
c-ares (http://daniel.haxx.se/projects/c-ares/)
or
ruli (http://www.nongnu.org/ruli/)
installed on your system to get DNS SRV lookup support
compiled into your sipsak binary.
INSTALLATION
============
The usual
./configure
make
followed by an optional
make install
if the binary should be available for all users on that host.
USAGE
=====
Please read the man page. It also contains some typical usage
examples at the end. Or check the website (http://sipsak.org)
for more/other examples.
FEEDBACK
========
Any kind of feedback is always welcome. Please send it to the
mailing list at sipsak@lists.sipsak.org (subscription required).
Have fun
Nils

16
TODO

@ -0,0 +1,16 @@
ToDo List (no order):
- fix: wrong nonce value after aprox. 2000 users
- fix: after aprox. 3 users the password is missing except -p was set
- add displayname support to parse_uri
- check the request target for the ACK
- add option to tear down INVITED calls with BYE
- add support for CANCEL
- add support for spoofed IPs
- parse the complete DNS resonses in util
- increase hostname detection for the Via line
- add support for priority and weigth in SRV responses
- endless randtrash mode with logfile
- support for IPv6
- strict RR support
Feel free to send me patches for this (or other) features!

@ -0,0 +1,376 @@
AC_DEFUN([SIPSAK_IP_UDP],
[
AC_CHECK_HEADERS([netinet/ip.h netinet/udp.h],,,
[[#ifdef HAVE_NETINET_IN_SYSTM_H
#include <sys/types.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#endif
]])
])
AC_DEFUN([SIPSAK_ICMP],
[
AC_CHECK_HEADERS([netinet/ip_icmp.h],,,
[[#ifdef HAVE_NETINET_IN_SYSTM_H
#include <sys/types.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#endif
#ifdef HAVE_NETINET_IP_H
#include <netinet/ip.h>
#endif
]])
])
AC_DEFUN([SIPSAK_TIMER],
[
# Check for T1 timer value
def_timeout=500
AC_ARG_ENABLE([timeout],AS_HELP_STRING(--enable-timeout=SEC,SIP timer T1 in SEC milliseconds (default 500)),[def_timeout=$enableval])
if test "X$def_timeout" = "Xno"; then
# no timeout makes no sense
def_timeout=500
fi
AC_DEFINE_UNQUOTED(DEFAULT_TIMEOUT, $def_timeout, [Default maximum timeout on waiting for response.])
])
AC_DEFUN([CHECK_LIB_CARES],
[
AC_MSG_CHECKING([for ares_version.h])
ares_incdir=NONE
ares_libdir=NONE
ares_libcall=NONE
ares_incdirs="/usr/include /usr/local/include /sw/include"
ares_libdirs="/usr/lib64 /usr/lib /usr/local/lib64 /usr/local/lib /sw/lib"
ares_libexten=".so .dylib .a"
for dir in $ares_incdirs; do
try="$dir/ares_version.h"
if test -f $try; then
ares_incdir=$dir;
break;
fi
done
if test "$ares_incdir" = "NONE"; then
AC_MSG_RESULT([not found])
else
AC_MSG_RESULT([found at $ares_incdir])
AC_MSG_CHECKING([for c-ares lib])
for dir in $ares_libdirs; do
for extension in $ares_libexten; do
try="$dir/libcares$extension"
if test -f $try; then
ares_libdir=$dir;
ares_libcall=cares;
break;
fi
done
if test "$ares_libdir" != "NONE"; then
break;
fi
done
if test "$ares_libdir" = "NONE"; then
AC_MSG_RESULT([not found])
else
AC_MSG_RESULT([found at $ares_libdir])
fi
AC_CHECK_LIB(cares, ares_version,
AC_DEFINE([HAVE_CARES_H], [1], [Has cares.h])
LIBS="$LIBS -L$ares_libdir -l$ares_libcall"
CFLAGS="$CFLAGS -I$ares_incdir"
SIPSAK_HAVE_ARES="1"
AC_SUBST(SIPSAK_HAVE_ARES)
)
fi
])
AC_DEFUN([CHECK_LIB_RULI],
[
AC_MSG_CHECKING([for ruli.h])
ruli_incdir=NONE
ruli_libdir=NONE
ruli_incdirs="/usr/include /usr/local/include /sw/include"
ruli_libdirs="/usr/lib64 /usr/lib /usr/local/lib64 /usr/local/lib /sw/lib"
ruli_libexten=".so .dylib .a"
for dir in $ruli_incdirs; do
try="$dir/ruli.h"
if test -f $try; then
ruli_incdir=$dir;
break;
fi
done
if test "$ruli_incdir" = "NONE"; then
AC_MSG_RESULT([not found])
else
AC_MSG_RESULT([found at $ruli_incdir])
AC_MSG_CHECKING([for libruli])
for dir in $ruli_libdirs; do
for extension in $ruli_libexten; do
try="$dir/libruli$extension"
if test -f $try; then
ruli_libdir=$dir;
break;
fi
done
if test "$ruli_libdir" != "NONE"; then
break;
fi
done
if test "$ruli_libdir" = "NONE"; then
AC_MSG_RESULT([not found])
else
AC_MSG_RESULT([found at $ruli_libdir])
fi
AC_CHECK_LIB(ruli, ruli_sync_query,
AC_DEFINE([HAVE_RULI_H], [1], [Has ruli.h])
LIBS="$LIBS -L$ruli_libdir -lruli"
CFLAGS="$CFLAGS -I$ruli_incdir"
)
fi
])
AC_DEFUN([CHECK_PROG_DISTCC],
[
AC_MSG_CHECKING([for distcc])
AC_ARG_ENABLE([distcc],
AC_HELP_STRING([--enable-distcc], [compile in parallel with distcc]),
[
distcc_dirs="/ /usr /usr/local /usr/local/gnu /usr/gnu"
for dir in $distcc_dirs; do
if test -x "$dir/bin/distcc"; then
found_distcc=yes;
DISTCC="$dir/bin/distcc"
break;
fi
done
if test x_$found_distcc != x_yes; then
AC_MSG_ERROR([not found])
else
AC_MSG_RESULT([yes])
AC_SUBST([DISTCC])
fi
],
[ AC_MSG_RESULT([not requested])
])
])
dnl Autoconf macros for libgnutls
dnl $id$
# Modified for LIBGNUTLS -- nmav
# Configure paths for LIBGCRYPT
# Shamelessly stolen from the one of XDELTA by Owen Taylor
# Werner Koch 99-12-09
dnl AM_PATH_LIBGNUTLS([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND ]]])
dnl Test for libgnutls, and define LIBGNUTLS_CFLAGS and LIBGNUTLS_LIBS
dnl
AC_DEFUN([AM_PATH_SIPSAK_LIBGNUTLS], [
dnl
dnl Get the cflags and libraries from the libgnutls-config script
dnl
AC_MSG_CHECKING([disabled gnutls])
AC_ARG_ENABLE([gnutls],
AC_HELP_STRING([--disable-gnutls], [compile without gnutls]),
[
AC_MSG_RESULT([yes])
DISABLE_GNUTLS=yes
AC_SUBST([DISABLE_GNUTLS])
],
[AC_MSG_RESULT([not requested])]
)
AC_ARG_WITH(libgnutls-prefix,
[ --with-libgnutls-prefix=PFX Prefix where libgnutls is installed (optional)],
libgnutls_config_prefix="$withval", libgnutls_config_prefix="")
if test x$libgnutls_config_prefix != x ; then
if test x${LIBGNUTLS_CONFIG+set} != xset ; then
LIBGNUTLS_CONFIG=$libgnutls_config_prefix/bin/libgnutls-config
fi
fi
if test "$DISABLE_GNUTLS" != "yes"; then
AC_PATH_PROG(LIBGNUTLS_CONFIG, libgnutls-config, no)
fi
min_libgnutls_version=ifelse([$1], ,0.1.0,$1)
AC_MSG_CHECKING(for libgnutls - version >= $min_libgnutls_version)
no_libgnutls=""
if test "$DISABLE_GNUTLS" = "yes"; then
LIBGNUTLS_CONFIG=no
fi
if test "$LIBGNUTLS_CONFIG" = "no" ; then
no_libgnutls=yes
else
LIBGNUTLS_CFLAGS=`$LIBGNUTLS_CONFIG $libgnutls_config_args --cflags`
LIBGNUTLS_LIBS=`$LIBGNUTLS_CONFIG $libgnutls_config_args --libs`
libgnutls_config_version=`$LIBGNUTLS_CONFIG $libgnutls_config_args --version`
ac_save_CFLAGS="$CFLAGS"
ac_save_LIBS="$LIBS"
CFLAGS="$CFLAGS $LIBGNUTLS_CFLAGS"
LIBS="$LIBS $LIBGNUTLS_LIBS"
dnl
dnl Now check if the installed libgnutls is sufficiently new. Also sanity
dnl checks the results of libgnutls-config to some extent
dnl
rm -f conf.libgnutlstest
AC_TRY_RUN([
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <gnutls/gnutls.h>
int
main ()
{
system ("touch conf.libgnutlstest");
if( strcmp( gnutls_check_version(NULL), "$libgnutls_config_version" ) )
{
printf("\n*** 'libgnutls-config --version' returned %s, but LIBGNUTLS (%s)\n",
"$libgnutls_config_version", gnutls_check_version(NULL) );
printf("*** was found! If libgnutls-config was correct, then it is best\n");
printf("*** to remove the old version of LIBGNUTLS. You may also be able to fix the error\n");
printf("*** by modifying your LD_LIBRARY_PATH enviroment variable, or by editing\n");
printf("*** /etc/ld.so.conf. Make sure you have run ldconfig if that is\n");
printf("*** required on your system.\n");
printf("*** If libgnutls-config was wrong, set the environment variable LIBGNUTLS_CONFIG\n");
printf("*** to point to the correct copy of libgnutls-config, and remove the file config.cache\n");
printf("*** before re-running configure\n");
}
else if ( strcmp(gnutls_check_version(NULL), LIBGNUTLS_VERSION ) )
{
printf("\n*** LIBGNUTLS header file (version %s) does not match\n", LIBGNUTLS_VERSION);
printf("*** library (version %s)\n", gnutls_check_version(NULL) );
}
else
{
if ( gnutls_check_version( "$min_libgnutls_version" ) )
{
return 0;
}
else
{
printf("no\n*** An old version of LIBGNUTLS (%s) was found.\n",
gnutls_check_version(NULL) );
printf("*** You need a version of LIBGNUTLS newer than %s. The latest version of\n",
"$min_libgnutls_version" );
printf("*** LIBGNUTLS is always available from ftp://gnutls.hellug.gr/pub/gnutls.\n");
printf("*** \n");
printf("*** If you have already installed a sufficiently new version, this error\n");
printf("*** probably means that the wrong copy of the libgnutls-config shell script is\n");
printf("*** being found. The easiest way to fix this is to remove the old version\n");
printf("*** of LIBGNUTLS, but you can also set the LIBGNUTLS_CONFIG environment to point to the\n");
printf("*** correct copy of libgnutls-config. (In this case, you will have to\n");
printf("*** modify your LD_LIBRARY_PATH enviroment variable, or edit /etc/ld.so.conf\n");
printf("*** so that the correct libraries are found at run-time))\n");
}
}
return 1;
}
],, no_libgnutls=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"])
CFLAGS="$ac_save_CFLAGS"
LIBS="$ac_save_LIBS"
fi
if test "x$no_libgnutls" = x ; then
AC_MSG_RESULT(yes)
ifelse([$2], , :, [$2])
else
if test -f conf.libgnutlstest ; then
:
else
AC_MSG_RESULT(no)
fi
if test "$LIBGNUTLS_CONFIG" != "no" ; then
if test -f conf.libgnutlstest ; then
:
else
echo "*** Could not run libgnutls test program, checking why..."
CFLAGS="$CFLAGS $LIBGNUTLS_CFLAGS"
LIBS="$LIBS $LIBGNUTLS_LIBS"
AC_TRY_LINK([
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <gnutls/gnutls.h>
], [ return !!gnutls_check_version(NULL); ],
[ echo "*** The test program compiled, but did not run. This usually means"
echo "*** that the run-time linker is not finding LIBGNUTLS or finding the wrong"
echo "*** version of LIBGNUTLS. If it is not finding LIBGNUTLS, you'll need to set your"
echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point"
echo "*** to the installed location Also, make sure you have run ldconfig if that"
echo "*** is required on your system"
echo "***"
echo "*** If you have an old version installed, it is best to remove it, although"
echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH"
echo "***" ],
[ echo "*** The test program failed to compile or link. See the file config.log for the"
echo "*** exact error that occured. This usually means LIBGNUTLS was incorrectly installed"
echo "*** or that you have moved LIBGNUTLS since it was installed. In the latter case, you"
echo "*** may want to edit the libgnutls-config script: $LIBGNUTLS_CONFIG" ])
CFLAGS="$ac_save_CFLAGS"
LIBS="$ac_save_LIBS"
fi
fi
LIBGNUTLS_CFLAGS=""
LIBGNUTLS_LIBS=""
ifelse([$3], , :, [$3])
fi
rm -f conf.libgnutlstest
AC_SUBST(LIBGNUTLS_CFLAGS)
AC_SUBST(LIBGNUTLS_LIBS)
])
dnl
dnl Useful macros for autoconf to check for ssp-patched gcc
dnl 1.0 - September 2003 - Tiago Sousa <mirage@kaotik.org>
dnl
dnl About ssp:
dnl GCC extension for protecting applications from stack-smashing attacks
dnl http://www.research.ibm.com/trl/projects/security/ssp/
dnl
dnl Usage:
dnl After calling the correct AC_LANG_*, use the corresponding macro:
dnl
dnl GCC_STACK_PROTECT_CC
dnl checks -fstack-protector with the C compiler, if it exists then updates
dnl CFLAGS and defines ENABLE_SSP_CC
dnl
dnl GCC_STACK_PROTECT_CXX
dnl checks -fstack-protector with the C++ compiler, if it exists then updates
dnl CXXFLAGS and defines ENABLE_SSP_CXX
dnl
AC_DEFUN([SIPSAK_GCC_STACK_PROTECT_CC],[
ssp_cc=yes
if test "X$CC" != "X"; then
AC_MSG_CHECKING([whether ${CC} accepts -fstack-protector])
ssp_old_cflags="$CFLAGS"
CFLAGS="$CFLAGS -fstack-protector"
AC_TRY_COMPILE(,,, ssp_cc=no)
echo $ssp_cc
if test "X$ssp_cc" = "Xno"; then
CFLAGS="$ssp_old_cflags"
else
AC_DEFINE([ENABLE_SSP_CC], 1, [Define if SSP C support is enabled.])
fi
fi
])
dnl *-*wedit:notab*-* Please keep this as the last line.

1150
aclocal.m4 vendored

File diff suppressed because it is too large Load Diff

351
auth.c

@ -0,0 +1,351 @@
/*
* $Id: auth.c 397 2006-01-28 21:11:50Z calrissian $
*
* Copyright (C) 2002-2004 Fhg Fokus
* Copyright (C) 2004-2005 Nils Ohlmeier
*
* This file belongs to sipsak, a free sip testing tool.
*
* sipsak 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.
*
* sipsak 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.
*/
#include "sipsak.h"
#include "auth.h"
#include "exit_code.h"
#include "helper.h"
#include "md5.h"
#ifdef HAVE_OPENSSL_SHA1
# include <openssl/sha.h>
#endif
#define SIPSAK_ALGO_MD5 1
#define SIPSAK_ALGO_SHA1 2
/* converts a hash into hex output
taken from the RFC 2617 */
void cvt_hex(unsigned char *_b, unsigned char *_h, int length)
{
unsigned short i;
unsigned char j;
for (i = 0; i < length; i++) {
j = (_b[i] >> 4) & 0xf;
if (j <= (unsigned char)9) {
_h[i * 2] = (j + (unsigned char)'0');
} else {
_h[i * 2] = (unsigned char)(j + (unsigned char)'a' - (unsigned char)10);
}
j = _b[i] & 0xf;
if (j <= (unsigned char)9) {
_h[i * 2 + 1] = (j + (unsigned char)'0');
} else {
_h[i * 2 + 1] = (unsigned char)(j + (unsigned char)'a' - (unsigned char)10);
}
};
_h[2*length] = '\0';
}
/* check for, create and insert a auth header into the message */
void insert_auth(char *message, char *authreq)
{
char *auth, *begin, *end, *insert, *backup, *realm, *usern, *nonce;
char *method, *uri;
char *qop_tmp = NULL;
unsigned char ha1[SIPSAK_HASHLEN], ha2[SIPSAK_HASHLEN], resp[SIPSAK_HASHLEN];
unsigned char ha1_hex[SIPSAK_HASHHEXLEN+1], ha2_hex[SIPSAK_HASHHEXLEN+1], resp_hex[SIPSAK_HASHHEXLEN+1];
int qop_auth=0, proxy_auth=0, algo=0;
unsigned int cnonce;
MD5_CTX Md5Ctx;
#ifdef HAVE_OPENSSL_SHA1
SHA_CTX Sha1Ctx;
#endif
auth=begin=end=insert=backup=realm=usern=nonce=method=uri = NULL;
memset(&ha1[0], '\0', SIPSAK_HASHLEN);
memset(&ha2[0], '\0', SIPSAK_HASHLEN);
memset(&resp[0], '\0', SIPSAK_HASHLEN);
memset(&ha1_hex[0], '\0', SIPSAK_HASHHEXLEN+1);
memset(&ha2_hex[0], '\0', SIPSAK_HASHHEXLEN+1);
memset(&resp_hex[0], '\0', SIPSAK_HASHHEXLEN+1);
/* prevent double auth insertion */
if ((begin=STRCASESTR(message, AUTH_STR))!=NULL ||
(begin=STRCASESTR(message, PROXYAUZ_STR))!=NULL) {
fprintf(stderr, "request:\n%s\nresponse:\n%s\nerror: authorization failed\n "
" request already contains (Proxy-) Authorization, but "
"received 40[1|7], see above\n", message, authreq);
exit_code(2);
}
/* make a backup of all except the request line because for
simplicity we insert the auth header direct behind the request line */
insert=strchr(message, '\n');
if (!insert) {
printf("failed to find newline\n");
return;
}
insert++;
backup=str_alloc(strlen(insert)+1);
strncpy(backup, insert, strlen(insert));
begin=STRCASESTR(authreq, WWWAUTH_STR);
if (begin==NULL) {
begin=STRCASESTR(authreq, PROXYAUTH_STR);
proxy_auth = 1;
}
if (begin) {
/* make a copy of the auth header to prevent that our searches
hit content of other header fields */
end=strchr(begin, '\n');
auth=str_alloc((size_t)(end-begin+1));
strncpy(auth, begin, (size_t)(end-begin));
/* we support Digest with MD5 or SHA1 */
if ((begin=STRCASESTR(auth, "Basic"))!=NULL) {
fprintf(stderr, "%s\nerror: authentication method Basic is deprecated since"
" RFC 3261 and not supported by sipsak\n", authreq);
exit_code(3);
}
if ((begin=STRCASESTR(auth, "Digest"))==NULL) {
fprintf(stderr, "%s\nerror: couldn't find authentication method Digest in "
"the 40[1|7] response above\n", authreq);
exit_code(3);
}
if ((begin=STRCASESTR(auth, "algorithm="))!=NULL) {
begin+=10;
if ((STRNCASECMP(begin, "MD5", 3))==0 || (STRNCASECMP(begin, "\"MD5\"", 5))==0) {
algo = SIPSAK_ALGO_MD5;
}
#ifdef HAVE_OPENSSL_SHA1
else if ((STRNCASECMP(begin, "SHA1", 3))==0 || (STRNCASECMP(begin, "\"SHA1\"", 5))==0) {
algo = SIPSAK_ALGO_SHA1;
}
#endif
else {
fprintf(stderr, "\n%s\nerror: unsupported authentication algorithm\n", authreq);
exit_code(2);
}
}
else {
algo = SIPSAK_ALGO_MD5;
}
/* we need the username at some points */
if (auth_username != NULL) {
usern = auth_username;
}
else {
usern=str_alloc(strlen(username)+11);
if (nameend>0)
snprintf(usern, strlen(username)+10, "%s%i", username, namebeg);
else
snprintf(usern, strlen(username)+10, "%s", username);
}
/* extract the method from the original request */
end=strchr(message, ' ');
method=str_alloc((size_t)(end-message+1));
strncpy(method, message, (size_t)(end-message));
/* extract the uri also */
begin=end++;
begin++;
end=strchr(end, ' ');
uri=str_alloc((size_t)(end-begin+1));
strncpy(uri, begin, (size_t)(end-begin));
/* lets start with some basic stuff... username, uri and algorithm */
if (proxy_auth == 1) {
snprintf(insert, PROXYAUZ_STR_LEN+1, PROXYAUZ_STR);
insert+=PROXYAUZ_STR_LEN;
}
else {
snprintf(insert, AUTH_STR_LEN+1, AUTH_STR);
insert+=AUTH_STR_LEN;
}
snprintf(insert, strlen(usern)+14, "username=\"%s\", ", usern);
insert+=strlen(insert);
snprintf(insert, strlen(uri)+9, "uri=\"%s\", ", uri);
insert+=strlen(insert);
snprintf(insert, ALGO_STR_LEN+1, ALGO_STR);
insert+=ALGO_STR_LEN;
if (algo == SIPSAK_ALGO_MD5) {
snprintf(insert, MD5_STR_LEN+1, MD5_STR);
insert+=MD5_STR_LEN;
}
#ifdef HAVE_OPENSSL_SHA1
else if (algo == SIPSAK_ALGO_SHA1) {
snprintf(insert, SHA1_STR_LEN+1, SHA1_STR);
insert+=SHA1_STR_LEN;
}
#endif
/* search for the realm, copy it to request and extract it for hash*/
if ((begin=STRCASESTR(auth, REALM_STR))!=NULL) {
end=strchr(begin, ',');
if (!end)
end=strchr(begin, '\r');
strncpy(insert, begin, (size_t)(end-begin+1));
insert=insert+(end-begin+1);
if (*(insert-1) == '\r')
*(insert-1)=',';
snprintf(insert, 2, " ");
insert++;
begin+=REALM_STR_LEN+1;
end--;
realm=str_alloc((size_t)(end-begin+1));
strncpy(realm, begin, (size_t)(end-begin));
}
else {
fprintf(stderr, "%s\nerror: realm not found in 401 above\n", authreq);
exit_code(3);
}
/* copy opaque if needed */
if ((begin=STRCASESTR(auth, OPAQUE_STR))!=NULL) {
end=strchr(begin, ',');
if (!end) {
end=strchr(begin, '\r');
}
strncpy(insert, begin, (size_t)(end-begin+1));
insert=insert+(end-begin+1);
if (*(insert-1) == '\r')
*(insert-1)=',';
snprintf(insert, 2, " ");
insert++;
}
/* lets see if qop=auth is uspported */
if ((begin=STRCASESTR(auth, QOP_STR))!=NULL) {
if (STRCASESTR(begin, QOPAUTH_STR)==NULL) {
fprintf(stderr, "response\n%s\nerror: qop \"auth\" not supported by"
" server\n", authreq);
exit_code(3);
}
qop_auth=1;
}
/* search, copy and extract the nonce */
if ((begin=STRCASESTR(auth, NONCE_STR))!=NULL) {
end=strchr(begin, ',');
if (!end)
end=strchr(begin, '\r');
strncpy(insert, begin, (size_t)(end-begin+1));
insert=insert+(end-begin+1);
if (*(insert-1) == '\r')
*(insert-1)=',';
snprintf(insert, 2, " ");
insert++;
begin+=NONCE_STR_LEN+1;
end--;
nonce=str_alloc((size_t)(end-begin+1));
strncpy(nonce, begin, (size_t)(end-begin));
}
else {
fprintf(stderr, "%s\nerror: nonce not found in 401 above\n", authreq);
exit_code(3);
}
/* if qop is supported we need som additional header */
if (qop_auth == 1) {
snprintf(insert, QOP_STR_LEN+QOPAUTH_STR_LEN+3, "%s%s, ", QOP_STR, QOPAUTH_STR);
insert+=strlen(insert);
nonce_count++;
snprintf(insert, NC_STR_LEN+11, "%s%08x, ", NC_STR, nonce_count);
insert+=strlen(insert);
cnonce=(unsigned int)rand();
snprintf(insert, 12+8, "cnonce=\"%x\", ", cnonce);
insert+=strlen(insert);
/* hopefully 100 is enough */
qop_tmp=str_alloc(100);
snprintf(qop_tmp, 8+8+8, "%08x:%x:auth:", nonce_count, cnonce);
}
/* if no password is given we try it with empty password */
if (!password)
password = EMPTY_STR;
if (algo == SIPSAK_ALGO_MD5) {
MD5Init(&Md5Ctx);
MD5Update(&Md5Ctx, usern, (unsigned int)strlen(usern));
MD5Update(&Md5Ctx, ":", 1);
MD5Update(&Md5Ctx, realm, (unsigned int)strlen(realm));
MD5Update(&Md5Ctx, ":", 1);
MD5Update(&Md5Ctx, password, (unsigned int)strlen(password));
MD5Final(&ha1[0], &Md5Ctx);
cvt_hex(&ha1[0], &ha1_hex[0], SIPSAK_HASHLEN_MD5);
MD5Init(&Md5Ctx);
MD5Update(&Md5Ctx, method, (unsigned int)strlen(method));
MD5Update(&Md5Ctx, ":", 1);
MD5Update(&Md5Ctx, uri, (unsigned int)strlen(uri));
MD5Final(&ha2[0], &Md5Ctx);
cvt_hex(&ha2[0], &ha2_hex[0], SIPSAK_HASHLEN_MD5);
MD5Init(&Md5Ctx);
MD5Update(&Md5Ctx, &ha1_hex, SIPSAK_HASHHEXLEN_MD5);
MD5Update(&Md5Ctx, ":", 1);
MD5Update(&Md5Ctx, nonce, (unsigned int)strlen(nonce));
MD5Update(&Md5Ctx, ":", 1);
if (qop_auth == 1) {
MD5Update(&Md5Ctx, qop_tmp, (unsigned int)strlen(qop_tmp));
}
MD5Update(&Md5Ctx, &ha2_hex, SIPSAK_HASHHEXLEN_MD5);
MD5Final(&resp[0], &Md5Ctx);
cvt_hex(&resp[0], &resp_hex[0], SIPSAK_HASHLEN_MD5);
}
#ifdef HAVE_OPENSSL_SHA1
else if (algo == SIPSAK_ALGO_SHA1) {
SHA1_Init(&Sha1Ctx);
SHA1_Update(&Sha1Ctx, usern, (unsigned int)strlen(usern));
SHA1_Update(&Sha1Ctx, ":", 1);
SHA1_Update(&Sha1Ctx, realm, (unsigned int)strlen(realm));
SHA1_Update(&Sha1Ctx, ":", 1);
SHA1_Update(&Sha1Ctx, password, (unsigned int)strlen(password));
SHA1_Final(&ha1[0], &Sha1Ctx);
cvt_hex(&ha1[0], &ha1_hex[0], SIPSAK_HASHLEN_SHA1);
SHA1_Init(&Sha1Ctx);
SHA1_Update(&Sha1Ctx, method, (unsigned int)strlen(method));
SHA1_Update(&Sha1Ctx, ":", 1);
SHA1_Update(&Sha1Ctx, uri, (unsigned int)strlen(uri));
SHA1_Final(&ha2[0], &Sha1Ctx);
cvt_hex(&ha2[0], &ha2_hex[0], SIPSAK_HASHLEN_SHA1);
SHA1_Init(&Sha1Ctx);
SHA1_Update(&Sha1Ctx, &ha1_hex, SIPSAK_HASHHEXLEN_SHA1);
SHA1_Update(&Sha1Ctx, ":", 1);
SHA1_Update(&Sha1Ctx, nonce, (unsigned int)strlen(nonce));
SHA1_Update(&Sha1Ctx, ":", 1);
if (qop_auth == 1) {
SHA1_Update(&Sha1Ctx, qop_tmp, (unsigned int)strlen(qop_tmp));
}
SHA1_Update(&Sha1Ctx, &ha2_hex, SIPSAK_HASHHEXLEN_SHA1);
SHA1_Final(&resp[0], &Sha1Ctx);
cvt_hex(&resp[0], &resp_hex[0], SIPSAK_HASHLEN_SHA1);
}
#endif
snprintf(insert, RESPONSE_STR_LEN+1, RESPONSE_STR);
insert+=RESPONSE_STR_LEN;
snprintf(insert, sizeof(resp_hex) + 8,"\"%s\"\r\n", &resp_hex[0]);
insert+=strlen(insert);
/* the auth header is complete, reinsert the rest of the request */
strncpy(insert, backup, strlen(backup));
}
else {
fprintf(stderr, "%s\nerror: couldn't find Proxy- or WWW-Authentication header"
" in the 401 response above\n", authreq);
exit_code(3);
}
if (verbose>1)
printf("authorizing\n");
/* hopefully we free all here */
free(backup);
free(auth);
free(method);
free(uri);
free(realm);
free(nonce);
if (auth_username == NULL) free(usern);
if (qop_auth == 1) free(qop_tmp);
}

@ -0,0 +1,25 @@
/*
* $Id: auth.h 397 2006-01-28 21:11:50Z calrissian $
*
* Copyright (C) 2002-2004 Fhg Fokus
* Copyright (C) 2004-2005 Nils Ohlmeier
*
* This file belongs to sipsak, a free sip testing tool.
*
* sipsak 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.
*
* sipsak 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.
*/
#ifndef SIPSAK_AUTH_H
#define SIPSAK_AUTH_H
void insert_auth(char *message, char *authreq);
#endif

1502
config.guess vendored

File diff suppressed because it is too large Load Diff

@ -0,0 +1,239 @@
/* config.h.in. Generated from configure.ac by autoheader. */
/* Default maximum timeout on waiting for response. */
#undef DEFAULT_TIMEOUT
/* Define if SSP C support is enabled. */
#undef ENABLE_SSP_CC
/* Define to 1 if you have the <arpa/inet.h> header file. */
#undef HAVE_ARPA_INET_H
/* Define to 1 if you have the <arpa/nameser.h> header file. */
#undef HAVE_ARPA_NAMESER_H
/* Define to 1 if you have the `calloc' function. */
#undef HAVE_CALLOC
/* Has cares.h */
#undef HAVE_CARES_H
/* The crypto lib has MD5 functions */
#undef HAVE_CRYPTO_WITH_MD5
/* The crpyto lib has SHA1 functions */
#undef HAVE_CRYPTO_WITH_SHA1
/* Define to 1 if you have the <ctype.h> header file. */
#undef HAVE_CTYPE_H
/* Define to 1 if you have the <cygwin/icmp.h> header file. */
#undef HAVE_CYGWIN_ICMP_H
/* Define to 1 if you have the <errno.h> header file. */
#undef HAVE_ERRNO_H
/* Define to 1 if you have the `getchar' function. */
#undef HAVE_GETCHAR
/* Define to 1 if you have the `getdomainname' function. */
#undef HAVE_GETDOMAINNAME
/* 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 `getopt' function. */
#undef HAVE_GETOPT
/* Define to 1 if you have the <getopt.h> header file. */
#undef HAVE_GETOPT_H
/* Define to 1 if you have the `getopt_long' function. */
#undef HAVE_GETOPT_LONG
/* Define to 1 if you have the `getpid' function. */
#undef HAVE_GETPID
/* Define to 1 if you have the `gettimeofday' function. */
#undef HAVE_GETTIMEOFDAY
/* Has gnutls */
#undef HAVE_GNUTLS
/* Define to 1 if you have the `inet_ntop' function. */
#undef HAVE_INET_NTOP
/* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H
/* Define to 1 if you have the <limits.h> header file. */
#undef HAVE_LIMITS_H
/* 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 <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 <netinet/in_systm.h> header file. */
#undef HAVE_NETINET_IN_SYSTM_H
/* Define to 1 if you have the <netinet/ip.h> header file. */
#undef HAVE_NETINET_IP_H
/* Define to 1 if you have the <netinet/ip_icmp.h> header file. */
#undef HAVE_NETINET_IP_ICMP_H
/* Define to 1 if you have the <netinet/udp.h> header file. */
#undef HAVE_NETINET_UDP_H
/* Define to 1 if you have the `ntohs' function. */
#undef HAVE_NTOHS
/* Define to 1 if you have the <openssl/md5.h> header file. */
#undef HAVE_OPENSSL_MD5_H
/* Define to 1 if you have the <openssl/sha.h> header file. */
#undef HAVE_OPENSSL_SHA_H
/* Define to 1 if you have the `regcomp' function. */
#undef HAVE_REGCOMP
/* Define to 1 if you have the <regex.h> header file. */
#undef HAVE_REGEX_H
/* Has ruli.h */
#undef HAVE_RULI_H
/* Define to 1 if you have the `select' function. */
#undef HAVE_SELECT
/* Define to 1 if you have the <signal.h> header file. */
#undef HAVE_SIGNAL_H
/* 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 <stdio.h> header file. */
#undef HAVE_STDIO_H
/* Define to 1 if you have the <stdlib.h> header file. */
#undef HAVE_STDLIB_H
/* Define to 1 if you have the `strcasestr' function. */
#undef HAVE_STRCASESTR
/* Define to 1 if you have the `strchr' function. */
#undef HAVE_STRCHR
/* Define to 1 if you have the `strcmp' function. */
#undef HAVE_STRCMP
/* 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 `strstr' function. */
#undef HAVE_STRSTR
/* Define to 1 if you have the `strtol' function. */
#undef HAVE_STRTOL
/* Define to 1 if you have the <sys/param.h> header file. */
#undef HAVE_SYS_PARAM_H
/* Define to 1 if you have the <sys/poll.h> header file. */
#undef HAVE_SYS_POLL_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 the <sys/utsname.h> header file. */
#undef HAVE_SYS_UTSNAME_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
/* 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 home page for this package. */
#undef PACKAGE_URL
/* Define to the version of this package. */
#undef PACKAGE_VERSION
/* 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
/* Version number of package */
#undef VERSION
/* Define to rpl_malloc if the replacement function should be used. */
#undef malloc
/* Define to `unsigned int' if <sys/types.h> does not define. */
#undef size_t

1714
config.sub vendored

File diff suppressed because it is too large Load Diff

6636
configure vendored

File diff suppressed because it is too large Load Diff

@ -0,0 +1,88 @@
# -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.
AC_PREREQ(2.59)
AC_INIT([sipsak],[0.9.6],[nils@sipsak.org])
AM_INIT_AUTOMAKE
AM_MAINTAINER_MODE
AC_CONFIG_SRCDIR([sipsak.c])
AC_CONFIG_HEADER([config.h])
# Checks for programs.
AC_PROG_CC
# Add -Wall if we are using GCC
if test "x$GCC" = "xyes"; then
CFLAGS="$CFLAGS -Wall"
fi
SIPSAK_GCC_STACK_PROTECT_CC
CHECK_PROG_DISTCC
AC_PROG_INSTALL
# Checks for libraries.
AC_CANONICAL_HOST
case "$host" in
*-*-solaris*)
LIBS="$LIBS -lposix4 -lsocket -lnsl"
;;
*)
LIBS="$LIBS"
;;
esac
AC_SUBST([LIBS])
# Checks for header files.
AC_HEADER_STDC
AC_CHECK_HEADERS([ctype.h errno.h arpa/inet.h netdb.h netinet/in.h netinet/in_systm.h limits.h sys/poll.h regex.h signal.h stdlib.h stdio.h string.h sys/param.h sys/socket.h sys/time.h unistd.h sys/utsname.h],,[AC_MSG_ERROR([missing required header (see above)])],)
AC_CHECK_HEADERS([getopt.h])
AC_HEADER_SYS_WAIT
AC_HEADER_TIME
SIPSAK_IP_UDP
SIPSAK_ICMP
AC_CHECK_HEADERS([cygwin/icmp.h],,,)
# Checks for typedefs, structures, and compiler characteristics.
AC_TYPE_SIZE_T
AC_HEADER_TIME
# Checks for library functions.
AC_FUNC_MALLOC
AC_FUNC_SELECT_ARGTYPES
AC_CHECK_FUNCS([getchar gethostbyname gethostname getopt getpid gettimeofday memset ntohs regcomp select socket strchr strcmp strstr strtol uname],,[AC_MSG_ERROR([missing required function (see above)])])
AC_CHECK_FUNCS([calloc getdomainname getopt_long inet_ntop strncasecmp strcasestr])
PKG_CHECK_MODULES([LIBGNUTLS], [gnutls >= 1.0.0],
AC_DEFINE([HAVE_GNUTLS], [1], [Has gnutls])
LIBS="$LIBS $LIBGNUTLS_LIBS -lgnutls-openssl"
CFLAGS="$CFLAGS $LIBGNUTLS_CFLAGS"
)
if test "X$LIBGNUTLS_LIBS" == "X";then
AC_CHECK_HEADERS([openssl/md5.h],
AC_CHECK_LIB(crypto, MD5_Init,
AC_DEFINE([HAVE_CRYPTO_WITH_MD5], [1], [The crypto lib has MD5 functions])
LIBS="$LIBS -lcrypto"
)
)
fi
AC_CHECK_HEADERS([openssl/sha.h],
AC_CHECK_LIB(crypto, SHA1_Init,
AC_DEFINE([HAVE_CRYPTO_WITH_SHA1], [1], [The crpyto lib has SHA1 functions])
LIBS="$LIBS -lcrypto"
)
)
CHECK_LIB_CARES
if test "X$SIPSAK_HAVE_ARES" == "X"; then
CHECK_LIB_RULI
else
AC_CHECK_HEADERS([arpa/nameser.h])
fi
SIPSAK_TIMER
AC_CONFIG_FILES([Makefile])
AC_OUTPUT

118
debian/changelog vendored

@ -0,0 +1,118 @@
sipsak (0.9.6+sipwise1) unstable; urgency=low
* Set --default-timeout from 500ms to 150ms in configure
* Abort after hitting timeout.
-- Andreas Granig <agranig@sipwise.com> Wed, 21 Sep 2011 15:12:49 +0200
sipsak (0.9.6-2.1) unstable; urgency=low
* Non-maintainer upload.
* Switch GnuTLS detection to pkg-config. Closes: #529909
-- Andreas Metzler <ametzler@debian.org> Sun, 29 Nov 2009 09:24:31 +0100
sipsak (0.9.6-2) unstable; urgency=low
* Adopt the package by the Debian VoIP team per request of the old
maintainer, ARAKI Yasuhiro.
* Incorporate previous NMUs.
* Bump Standards-Version to 3.7.3.
-- Faidon Liambotis <paravoid@debian.org> Wed, 23 Jan 2008 11:09:07 +0200
sipsak (0.9.6-1.2) unstable; urgency=high
* Non-maintainer upload by the Debian VoIP team.
* Urgency high because of an RC bugfix.
* Mention all the copyright holders and GPLv2 "or later" in
debian/copyright. (Closes: #456440)
* Fix debian/watch by using a v3 watchfile. (Closes: #450083)
* Don't ship an empty /usr/sbin.
-- Faidon Liambotis <paravoid@debian.org> Tue, 22 Jan 2008 11:07:01 +0200
sipsak (0.9.6-1.1) unstable; urgency=low
* NMU
* Substitute AC_TRY_COMPILE with AC_TRY_LINK, fixing FTBFS with gcc-4.1
(Closes: #358643)
-- Julien Danjou <acid@debian.org> Tue, 30 May 2006 14:54:40 +0200
sipsak (0.9.6-1) unstable; urgency=low
* New upstream release
-- ARAKI Yasuhiro <ar@debian.org> Tue, 31 Jan 2006 13:14:05 +0900
sipsak (0.9.5-1) unstable; urgency=low
* New upstream release. Currently disabled 'c-ares'. Because c-ares is not packaged for Debian.
-- ARAKI Yasuhiro <ar@debian.org> Mon, 21 Nov 2005 16:32:41 +0900
sipsak (0.9.2-2) unstable; urgency=low
* fix: Add the missing Build-Depends on 'libgnutls-dev' to debian/control. (Closes: #329779)
-- ARAKI Yasuhiro <ar@debian.org> Tue, 4 Oct 2005 14:43:09 +0900
sipsak (0.9.2-1) unstable; urgency=low
* New upstream release
* fix: sipsak try to connect wrong port under no SRV record.
(Closes: #328262)
-- ARAKI Yasuhiro <ar@debian.org> Fri, 23 Sep 2005 02:18:30 +0900
sipsak (0.9.1-2) unstable; urgency=low
* Apply for debian-policy 3.6.2.1.
-- ARAKI Yasuhiro <ar@debian.org> Mon, 29 Aug 2005 21:01:54 +0900
sipsak (0.9.1-1) unstable; urgency=low
* New upstream release
* DNS SRV support with libruli4.
-- ARAKI Yasuhiro <ar@debian.org> Fri, 5 Aug 2005 12:35:19 +0900
sipsak (0.8.12-1) unstable; urgency=low
* New upstream release
-- araki yasuhiro <ar@debian.org> Wed, 4 May 2005 17:44:08 +0900
sipsak (0.8.11-1) unstable; urgency=low
* New upstream release
-- ARAKI Yasuhiro <ar@debian.org> Fri, 4 Feb 2005 14:21:30 +0900
sipsak (0.8.10-1) unstable; urgency=low
* New upstream release
* Add debian/watch
-- ARAKI Yasuhiro <ar@debian.org> Fri, 8 Oct 2004 16:41:31 +0900
sipsak (0.8.7-3) unstable; urgency=low
* Description fix. Last version is not fixed.. (Closes: #242285)
-- ARAKI Yasuhiro <ar@debian.org> Tue, 6 Apr 2004 11:26:40 +0900
sipsak (0.8.7-2) unstable; urgency=low
* Description fix. (Closes: #242285)
-- ARAKI Yasuhiro <ar@debian.org> Tue, 6 Apr 2004 10:53:00 +0900
sipsak (0.8.7-1) unstable; urgency=low
* Initial Release. (Closes: #239984)
-- ARAKI Yasuhiro <ar@debian.org> Thu, 25 Mar 2004 13:37:46 +0900

1
debian/compat vendored

@ -0,0 +1 @@
4

16
debian/control vendored

@ -0,0 +1,16 @@
Source: sipsak
Section: net
Priority: optional
Maintainer: Debian VoIP Team <pkg-voip-maintainers@lists.alioth.debian.org>
Uploaders: Faidon Liambotis <paravoid@debian.org>
Build-Depends: debhelper (>= 4.0.0), libruli4-dev, libgnutls-dev, pkg-config
Standards-Version: 3.7.3
Package: sipsak
Architecture: any
Depends: ${shlibs:Depends}
Description: SIP Swiss army knife
sipsak is a small command line tool for developers and administrators of
Session Initiation Protocol (SIP) applications.
It can be used for some simple tests on SIP applications and devices.

26
debian/copyright vendored

@ -0,0 +1,26 @@
This package was debianized by ARAKI Yasuhiro <ar@debian.org> on
Thu, 25 Mar 2004 13:37:46 +0900.
It was downloaded from http://sipsak.berlios.de/.
Upstream Author: Nils Ohlmeier <ohlmeier at fokus dot frauenhofer dot de>
Copyright:
Copyright (C) 2002-2004 Fhg Fokus
Copyright (C) 2004-2005 Nils Ohlmeier
sipsak 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.
sipsak is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License with
your Debian GNU/Linux system, in /usr/share/common-licenses/GPL, or with
the Debian GNU/Linux sipsak source package as the file COPYING. If not,
write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
Boston, MA 02110-1301 USA

1
debian/dirs vendored

@ -0,0 +1 @@
usr/bin

4
debian/docs vendored

@ -0,0 +1,4 @@
NEWS
TODO
AUTHORS

90
debian/rules vendored

@ -0,0 +1,90 @@
#!/usr/bin/make -f
# -*- makefile -*-
# Sample debian/rules that uses debhelper.
# GNU copyright 1997 to 1999 by Joey Hess.
# Uncomment this to turn on verbose mode.
#export DH_VERBOSE=1
# These are used for cross-compiling and for saving the configure script
# from having to guess our platform (since we know it already)
DEB_HOST_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE)
DEB_BUILD_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE)
CFLAGS = -Wall -g
ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS)))
CFLAGS += -O0
else
CFLAGS += -O2
endif
ifeq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS)))
INSTALL_PROGRAM += -s
endif
config.status: configure
dh_testdir
# Add here commands to configure the package.
CFLAGS="$(CFLAGS)" ./configure \
--host=$(DEB_HOST_GNU_TYPE) \
--build=$(DEB_BUILD_GNU_TYPE) \
--prefix=/usr \
--mandir=\$${prefix}/share/man \
--infodir=\$${prefix}/share/info \
--enable-timeout=150
build: build-stamp
build-stamp: config.status
dh_testdir
$(MAKE)
touch build-stamp
clean:
dh_testdir
dh_testroot
rm -f build-stamp
-$(MAKE) distclean
ifneq "$(wildcard /usr/share/misc/config.sub)" ""
cp -f /usr/share/misc/config.sub config.sub
endif
ifneq "$(wildcard /usr/share/misc/config.guess)" ""
cp -f /usr/share/misc/config.guess config.guess
endif
dh_clean
install: build
dh_testdir
dh_testroot
dh_clean -k
dh_installdirs
$(MAKE) install DESTDIR=$(CURDIR)/debian/sipsak
binary-indep: build install
# We have nothing to do by default.
binary-arch: build install
dh_testdir
dh_testroot
dh_installchangelogs ChangeLog
dh_installdocs
dh_installexamples
# dh_install
dh_installman
dh_link
dh_strip
dh_compress
dh_fixperms
dh_installdeb
dh_shlibdeps
dh_gencontrol
dh_md5sums
dh_builddeb
binary: binary-indep binary-arch
.PHONY: build clean binary-indep binary-arch binary install

5
debian/watch vendored

@ -0,0 +1,5 @@
version=3
opts=downloadurlmangle=s/prdownload/download/,uversionmangle=s/-.*$// \
http://developer.berlios.de/project/showfiles.php?group_id=485 \
http://prdownload.berlios.de/sipsak/sipsak-(.*)\.tar\.gz

@ -0,0 +1,526 @@
#! /bin/sh
# depcomp - compile a program generating dependencies as side-effects
scriptversion=2004-04-25.13
# Copyright (C) 1999, 2000, 2003, 2004 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'.
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 0
;;
-v | --v*)
echo "depcomp $scriptversion"
exit 0
;;
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
# `libtool' can also be set to `yes' or `no'.
if test -z "$depfile"; then
base=`echo "$object" | sed -e 's,^.*/,,' -e 's,\.\([^.]*\)$,.P\1,'`
dir=`echo "$object" | sed 's,/.*$,/,'`
if test "$dir" = "$object"; then
dir=
fi
# FIXME: should be _deps on DOS.
depfile="$dir.deps/$base"
fi
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
# Dependencies are output in .lo.d with libtool 1.4.
# They are output in .o.d with libtool 1.5.
tmpdepfile1="$dir.libs/$base.lo.d"
tmpdepfile2="$dir.libs/$base.o.d"
tmpdepfile3="$dir.libs/$base.d"
"$@" -Wc,-MD
else
tmpdepfile1="$dir$base.o.d"
tmpdepfile2="$dir$base.d"
tmpdepfile3="$dir$base.d"
"$@" -MD
fi
stat=$?
if test $stat -eq 0; then :
else
rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
exit $stat
fi
if test -f "$tmpdepfile1"; then
tmpdepfile="$tmpdepfile1"
elif test -f "$tmpdepfile2"; then
tmpdepfile="$tmpdepfile2"
else
tmpdepfile="$tmpdepfile3"
fi
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:

@ -0,0 +1,63 @@
/*
* $Id: exit_code.c 397 2006-01-28 21:11:50Z calrissian $
*
* Copyright (C) 2002-2004 Fhg Fokus
* Copyright (C) 2004-2005 Nils Ohlmeier
*
* This file belongs to sipsak, a free sip testing tool.
*
* sipsak 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.
*
* sipsak 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.
*/
#if HAVE_CONFIG_H
# include "config.h"
#endif
#ifdef HAVE_STDIO_H
# include <stdio.h>
#endif
#ifdef HAVE_STDLIB_H
# include <stdlib.h>
#endif
#include "exit_code.h"
enum exit_modes exit_mode = EM_DEFAULT;
void exit_code(int code)
{
switch(exit_mode) {
case EM_DEFAULT:
if (code == 4) {
exit(0);
}
else {
exit(code);
}
case EM_NAGIOS:
if (code == 0) {
printf("SIP ok\n");
exit(0);
}
else if (code == 4) {
printf("SIP warning\n");
exit(1);
}
else {
printf("SIP failure\n");
exit(2);
}
default:
fprintf(stderr, "ERROR: unknown exit code\n");
exit(1);
}
}

@ -0,0 +1,29 @@
/*
* $Id: exit_code.h 397 2006-01-28 21:11:50Z calrissian $
*
* Copyright (C) 2002-2004 Fhg Fokus
* Copyright (C) 2004-2005 Nils Ohlmeier
*
* This file belongs to sipsak, a free sip testing tool.
*
* sipsak 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.
*
* sipsak 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.
*/
#ifndef SIPSAK_EXITCODE_H
#define SIPSAK_EXITCODE_H
enum exit_modes { EM_DEFAULT, EM_NAGIOS };
extern enum exit_modes exit_mode;
void exit_code( int code );
#endif

@ -0,0 +1,614 @@
/*
* $Id: header_f.c 397 2006-01-28 21:11:50Z calrissian $
*
* Copyright (C) 2002-2004 Fhg Fokus
* Copyright (C) 2004-2005 Nils Ohlmeier
*
* This file belongs to sipsak, a free sip testing tool.
*
* sipsak 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.
*
* sipsak 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.
*/
#include "sipsak.h"
#include "header_f.h"
#include "exit_code.h"
#include "helper.h"
#include "shoot.h"
/* add the given header(s) below the request line */
void insert_header(char *mes, char *header, int first) {
char *ins, *backup;
if (first) {
ins = strchr(mes, '\n');
if (ins == NULL) {
printf("failed to find a new line in the message\n");
exit_code(2);
}
ins++;
}
else {
ins = mes;
}
backup = str_alloc(strlen(ins) + 1);
strncpy(backup, ins, strlen(ins));
strncpy(ins, header, strlen(header));
strncpy(ins + strlen(header), backup, strlen(backup)+1);
free(backup);
}
/* add a Via Header Field in the message. */
void add_via(char *mes)
{
char *via_line, *via, *backup;
if ((via=STRCASESTR(mes, VIA_STR)) == NULL &&
(via=STRCASESTR(mes, VIA_SHORT_STR)) == NULL) {
/* We didn't found a Via so we insert our via
direct after the first line. */
via=strchr(mes,'\n');
if(via == NULL) {
fprintf(stderr, "error: failed to find a position to insert Via:\n"
"'%s'\n", mes);
exit_code(2);
}
via++;
}
if (*via == '\n')
via++;
/* build our own Via-header-line */
via_line = str_alloc(VIA_SIP_STR_LEN+TRANSPORT_STR_LEN+1+
strlen(fqdn)+15+30+1);
snprintf(via_line,
VIA_SIP_STR_LEN+TRANSPORT_STR_LEN+1+strlen(fqdn)+15+30,
"%s%s %s:%i;branch=z9hG4bK.%08x;rport;alias\r\n",
VIA_SIP_STR, transport_str, fqdn, lport, rand());
if (verbose > 2)
printf("our Via-Line: %s\n", via_line);
if (strlen(mes)+strlen(via_line)>= BUFSIZE){
printf("can't add our Via Header Line because file is too big\n");
exit_code(2);
}
/* finnaly make a backup, insert our via and append the backup */
backup=str_alloc((strlen(via)+1));
strncpy(backup, via, strlen(via));
strncpy(via, via_line, strlen(via_line));
strncpy(via+strlen(via_line), backup, strlen(backup)+1);
if (verbose > 2)
printf("New message with Via-Line:\n%s\n", mes);
free(via_line);
free(backup);
}
/* copy the via lines from the message to the message
reply for correct routing of our reply.
*/
void cpy_vias(char *reply, char *dest){
char *first_via, *middle_via, *last_via, *backup;
/* lets see if we find any via */
if ((first_via=STRCASESTR(reply, VIA_STR))==NULL &&
(first_via=STRCASESTR(reply, VIA_SHORT_STR))==NULL ){
fprintf(stderr, "error: the received message doesn't contain a Via header\n");
exit_code(3);
}
last_via=first_via+4;
middle_via=last_via;
/* proceed additional via lines */
while ((middle_via=STRCASESTR(last_via, VIA_STR))!=NULL ||
(middle_via=STRCASESTR(last_via, VIA_SHORT_STR))!=NULL )
last_via=middle_via+4;
last_via=strchr(last_via, '\n');
middle_via=strchr(dest, '\n')+1;
/* make a backup, insert the vias after the first line and append
backup
*/
backup=str_alloc(strlen(middle_via)+1);
strcpy(backup, middle_via);
strncpy(middle_via, first_via, (size_t)(last_via-first_via+1));
strcpy(middle_via+(last_via-first_via+1), backup);
free(backup);
if (verbose > 2)
printf("message reply with vias included:\n%s\n", dest);
}
void cpy_to(char *reply, char *dest) {
char *src_to, *dst_to, *backup, *tmp;
/* find the position where we want to insert the To */
if ((dst_to=STRCASESTR(dest, TO_STR))==NULL &&
(dst_to=STRCASESTR(dest, TO_SHORT_STR))==NULL) {
fprintf(stderr, "error: could not find To in the destination: %s\n", dest);
exit_code(2);
}
if (*dst_to == '\n')
dst_to++;
/* find the To we want to copy */
if ((src_to=STRCASESTR(reply, TO_STR))==NULL &&
(src_to=STRCASESTR(reply, TO_SHORT_STR))==NULL) {
if (verbose > 0)
fprintf(stderr, "warning: could not find To in reply. "
"trying with original To\n");
}
else {
if (*src_to == '\n')
src_to++;
/* both To found, so copy it */
tmp=strchr(dst_to, '\n');
tmp++;
backup=str_alloc(strlen(tmp)+1);
strcpy(backup, tmp);
tmp=strchr(src_to, '\n');
strncpy(dst_to, src_to, (size_t)(tmp-src_to+1));
strcpy(dst_to+(tmp-src_to+1), backup);
free(backup);
if (verbose >2)
printf("reply with copyed To:\n%s\n", dest);
}
}
/* check for the existence of a Max-Forwards header field. if its
present it sets it to the given value, if not it will be inserted.*/
void set_maxforw(char *mes, int value){
char *max, *backup, *crlfi;
int maxforward;
if ((max=STRCASESTR(mes, MAX_FRW_STR))==NULL){
/* no max-forwards found so insert it after the first line*/
max=strchr(mes,'\n');
if (!max) {
printf("failed to find newline\n");
exit_code(254);
}
max++;
backup=str_alloc(strlen(max)+1);
strncpy(backup, max, (size_t)(strlen(max)));
if (value == -1) {
maxforward = 70; // RFC3261 default
}
else {
maxforward = value;
}
snprintf(max, MAX_FRW_STR_LEN+6, "%s%i\r\n", MAX_FRW_STR, maxforward);
max=strchr(max,'\n');
max++;
strncpy(max, backup, strlen(backup)+1);
free(backup);
if (verbose > 1)
printf("Max-Forwards %i inserted into header\n", maxforward);
if (verbose > 2)
printf("New message with inserted Max-Forwards:\n%s\n", mes);
}
else{
/* found max-forwards => overwrite the value with maxforw*/
crlfi=strchr(max,'\n');
crlfi++;
backup=str_alloc(strlen(crlfi)+1);
strncpy(backup, crlfi, strlen(crlfi));
crlfi=max + MAX_FRW_STR_LEN;
if (value == -1) {
maxforward = str_to_int(crlfi);
maxforward++;
}
else {
maxforward = value;
}
snprintf(crlfi, 6, "%i\r\n", maxforward);
crlfi=strchr(max,'\n');
crlfi++;
strncpy(crlfi, backup, strlen(backup)+1);
free(backup);
if (verbose > 1)
printf("Max-Forwards set to %i\n", maxforward);
if (verbose > 2)
printf("New message with changed Max-Forwards:\n%s\n", mes);
}
}
/* replaces the uri in first line of mes with the other uri */
void uri_replace(char *mes, char *uri)
{
char *foo, *backup;
foo=strchr(mes, '\n');
if (!foo) {
printf("failed to find newline\n");
exit_code(254);
}
foo++;
backup=str_alloc(strlen(foo)+1);
strncpy(backup, foo, strlen(foo));
foo=STRCASESTR(mes, "sip");
strncpy(foo, uri, strlen(uri));
strncpy(foo+strlen(uri), SIP20_STR, SIP20_STR_LEN);
strncpy(foo+strlen(uri)+SIP20_STR_LEN, backup, strlen(backup)+1);
free(backup);
if (verbose > 2)
printf("Message with modified uri:\n%s\n", mes);
}
/* replace the Content-Length value with the given value */
void set_cl(char* mes, int contentlen) {
char *cl, *cr, *backup;
if ((cl=STRCASESTR(mes, CON_LEN_STR)) == NULL &&
(cl=STRCASESTR(mes, CON_LEN_SHORT_STR)) == NULL) {
printf("missing Content-Length in message\n");
return;
}
if (*cl == '\n') {
cl++;
}
cr = strchr(cl, '\n');
cr++;
backup=str_alloc(strlen(cr)+1);
strncpy(backup, cr, strlen(cr));
if (*cl == 'C')
cr=cl + CON_LEN_STR_LEN;
else
cr=cl + 3;
snprintf(cr, 6, "%i\r\n", contentlen);
cr=strchr(cr, '\n');
cr++;
strncpy(cr, backup, strlen(backup)+1);
free(backup);
if (verbose > 2) {
printf("Content-Length set to %i\n"
"New message with changed Content-Length:\n%s\n", contentlen, mes);
}
}
/* returns the content length from the message; in case of error it
* return -1 */
int get_cl(char* mes) {
char *cl;
if ((cl=STRCASESTR(mes, CON_LEN_STR)) == NULL &&
(cl=STRCASESTR(mes, CON_LEN_SHORT_STR)) == NULL) {
if (verbose > 1)
printf("missing Content-Length in message\n");
return -1;
}
if (*cl == '\n') {
cl+=3;
}
else {
cl+=15;
}
return str_to_int(cl);
}
/* returns 1 if the rr_line contains the lr parameter
* otherwise 0 */
int find_lr_parameter(char *rr_line) {
char *eol, *lr;
eol = strchr(rr_line, '\n');
lr = STRCASESTR(rr_line, ";lr");
if ((eol == NULL) || (lr == NULL) || (lr > eol)) {
return 0;
}
else {
return 1;
}
}
/* copies the Record-Route header from src to dst.
* if route is set Record-Route will be replaced by Route */
void cpy_rr(char* src, char *dst, int route) {
char *rr, *cr, *cr2, *backup;
int len;
cr = strchr(dst, '\n');
if (cr == NULL) {
fprintf(stderr, "error: failed to end of line in destination\n");
exit_code(3);
}
cr++;
rr = STRCASESTR(src, RR_STR);
if (rr != NULL) {
if (find_lr_parameter(rr) == 0) {
fprintf(stderr, "error: strict routing is not support yet\n");
exit_code(252);
}
backup=str_alloc(strlen(cr)+1);
strncpy(backup, cr, strlen(cr));
if (route == 0)
len = RR_STR_LEN;
else
len = ROUTE_STR_LEN;
while (rr != NULL) {
if (route == 0) {
strncpy(cr, RR_STR, RR_STR_LEN);
}
else {
strncpy(cr, ROUTE_STR, ROUTE_STR_LEN);
}
cr += len;
cr2 = strchr(rr, '\n');
if (cr2 == NULL) {
fprintf(stderr, "error: failed to find end of line\n");
exit_code(3);
}
strncpy(cr, rr + RR_STR_LEN, (cr2 - (rr + len) + 1));
cr+=(cr2 - (rr + RR_STR_LEN) + 1);
rr = STRCASESTR(++rr, RR_STR);
}
strncpy(cr, backup, strlen(backup)+1);
free(backup);
if (verbose > 2)
printf("New message with inserted Route:\n%s\n", dst);
}
}
/* build an ACK from the given invite and reply.
* NOTE: space has to be allocated allready for the ACK */
void build_ack(char *invite, char *reply, char *dest,
struct sipsak_regexp *reg) {
char *tmp;
int len;
if ((tmp = STRCASESTR(invite, "\r\n\r\n")) != NULL) {
len = (tmp + 4) - invite;
}
else {
len = strlen(invite);
}
memcpy(dest, invite, len);
*(dest + len) = '\0';
replace_string(dest, "INVITE", "ACK");
set_cl(dest, 0);
cpy_to(reply, dest);
if (regexec(&(reg->okexp), reply, 0, 0, 0)==0) {
cpy_rr(reply, dest, 1);
/* 200 ACK must be in new transaction */
new_branch(dest);
if((tmp = uri_from_contact(reply))!= NULL) {
uri_replace(dest, tmp);
free(tmp);
}
}
}
/* tryes to find the warning header filed and prints out the IP */
void warning_extract(char *message)
{
char *warning, *end, *mid, *server;
int srvsize;
if ((warning=STRCASESTR(message, "Warning:"))==NULL) {
if (verbose > 0)
printf("'no Warning header found' ");
else
printf("?? ");
return;
}
end=strchr(warning, '"');
end--;
warning=strchr(warning, '3');
warning+=4;
mid=strchr(warning, ':');
if (mid)
end=mid;
srvsize=end - warning + 1;
server=str_alloc((size_t)srvsize);
server=strncpy(server, warning, (size_t)(srvsize - 1));
printf("%s ", server);
free(server);
}
/* tries to find and return the number in the CSeq header */
int cseq(char *message)
{
char *cseq;
int num=-1;
cseq=STRCASESTR(message, CSEQ_STR);
if (cseq) {
cseq+=6;
num=str_to_int(cseq);
if (num < 1) {
if (verbose > 2)
printf("CSeq found but not convertable\n");
return 0;
}
return num;
}
if (verbose > 2)
printf("no CSeq found\n");
return 0;
}
/* if it find the Cseq number in the message it will increased by one */
void increase_cseq(char *message)
{
int cs;
char *cs_s, *eol, *backup;
cs = cseq(message);
if ((cs < 1) && (verbose > 1)) {
printf("CSeq increase failed because unable to extract CSeq number\n");
return;
}
if (cs == INT_MAX)
cs = 1;
else
cs++;
cs_s=STRCASESTR(message, CSEQ_STR);
if (cs_s) {
cs_s+=6;
eol=strchr(cs_s, ' ');
eol++;
backup=str_alloc(strlen(eol)+1);
strncpy(backup, eol, (size_t)(strlen(eol)));
snprintf(cs_s, 11, "%i ", cs);
cs_s+=strlen(cs_s);
strncpy(cs_s, backup, strlen(backup));
free(backup);
cseq_counter = cs;
}
else if (verbose > 1)
printf("'CSeq' not found in message\n");
}
/* separates the given URI into the parts by setting the pointer but it
destroyes the URI */
void parse_uri(char *uri, char **scheme, char **user, char **host, int *port)
{
char *col, *col2, *at;
col = col2 = at = NULL;
*port = 0;
*scheme = *user = *host = NULL;
if ((col=strchr(uri,':'))!=NULL) {
if ((at=strchr(uri,'@'))!=NULL) {
*col = '\0';
*at = '\0';
if (at > col) {
*scheme = uri;
*user = ++col;
*host = ++at;
if ((col2=strchr(*host,':'))!=NULL) {
*col2 = '\0';
*port = str_to_int(++col2);
}
}
else {
*user = uri;
*host = ++at;
*port = str_to_int(++col);
}
}
else {
*col = '\0';
col++;
if ((col2=strchr(col,':'))!=NULL) {
*col2 = '\0';
*scheme = uri;
*host = col;
*port = str_to_int(++col2);
}
else {
if (is_number(col)) {
*host = uri;
*port = str_to_int(col);
}
else {
*scheme = uri;
*host = col;
}
}
}
}
else {
*host = uri;
}
}
/* return a copy of the URI from the Contact of the message if found */
char* uri_from_contact(char *message)
{
char *contact, *end, *tmp, c;
/* try to find the contact in the redirect */
if ((contact=STRCASESTR(message, CONT_STR))==NULL &&
(contact=STRCASESTR(message, CONT_SHORT_STR))==NULL ) {
if(verbose > 1)
printf("'Contact' not found in the message\n");
return NULL;
}
if (*contact == '\n')
contact++;
if((end=strchr(contact,'\r'))!=NULL) {
c = '\r';
*end = '\0';
}
else if((end=strchr(contact,'\n'))!=NULL) {
c = '\n';
*end = '\0';
}
else {
c = '\0';
end = contact + strlen(contact);
}
tmp = NULL;
if ((contact=STRCASESTR(contact, "sip:"))!=NULL) {
if ((tmp=strchr(contact+4, ';'))!=NULL) {
*end = c;
end = tmp;
c = *end;
*end = '\0';
}
if ((tmp=strchr(contact+4, '>'))!=NULL) {
*end = c;
end = tmp;
c = *end;
*end = '\0';
}
tmp = str_alloc(strlen(contact)+1);
memcpy(tmp,contact,strlen(contact));
}
*end = c;
return tmp;
}
/* replace the 8 bytes behind the first magic cookie with a new
* random value */
void new_branch(char *message)
{
char *branch;
char backup;
if((branch = STRCASESTR(message,"branch=z9hG4bK.")) != NULL) {
backup = *(branch+15+8);
snprintf(branch+15, 9, "%08x", rand());
*(branch+15+8) = backup;
}
}
/* increase the CSeq and insert a new branch value */
void new_transaction(char *message)
{
increase_cseq(message);
new_branch(message);
}
/* just print the first line of the message */
void print_message_line(char *message)
{
char *crlf;
crlf=strchr(message, '\n');
if (!crlf) {
printf("failed to find newline\n");
exit_code(254);
}
else if (*(crlf - 1) == '\r')
crlf--;
printf("%.*s\n", (int)(crlf - message), message);
}
/* return pointer to the beginning of the message body */
inline char* get_body(char *mes) {
char *cr;
if ((cr = strstr(mes, "\r\n\r\n")) != NULL) {
cr+=4;
}
return cr;
}

@ -0,0 +1,65 @@
/*
* $Id: header_f.h 397 2006-01-28 21:11:50Z calrissian $
*
* Copyright (C) 2002-2004 Fhg Fokus
* Copyright (C) 2004-2005 Nils Ohlmeier
*
* This file belongs to sipsak, a free sip testing tool.
*
* sipsak 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.
*
* sipsak 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.
*/
#ifndef SIPSAK_HEADER_H
#define SIPSAK_HEADER_H
#include "shoot.h"
void insert_header(char *mes, char *header, int first);
void add_via(char *mes);
void cpy_vias(char *reply, char *dest);
void cpy_to(char *reply, char *dest);
void set_maxforw(char *mes, int value);
void uri_replace(char *mes, char *uri);
void set_cl(char* mes, int contentlen);
int get_cl(char* mes);
int find_lr_parameter(char *rr_line);
void cpy_rr(char* src, char *dst, int route);
void build_ack(char *invite, char *reply, char *dest,
struct sipsak_regexp *reg);
void warning_extract(char *message);
int cseq(char *message);
void increase_cseq(char *message);
void parse_uri(char *uri, char **scheme, char **user, char **host, int *port);
char* uri_from_contact(char *message);
void new_branch(char *message);
void new_transaction(char *message);
void print_message_line(char *message);
inline char* get_body(char *mes);
#endif

@ -0,0 +1,821 @@
/*
* $Id: helper.c 397 2006-01-28 21:11:50Z calrissian $
*
* Copyright (C) 2002-2004 Fhg Fokus
* Copyright (C) 2004-2005 Nils Ohlmeier
*
* This file belongs to sipsak, a free sip testing tool.
*
* sipsak 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.
*
* sipsak 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.
*/
#include "sipsak.h"
#ifdef HAVE_NETDB_H
# include <netdb.h>
#endif
#ifdef HAVE_UNISTD_H
# ifdef HAVE_SYS_TYPES_H
# include <sys/types.h>
# endif
# include <unistd.h>
#endif
#ifdef HAVE_SYS_UTSNAME_H
# include <sys/utsname.h>
#endif
#ifdef HAVE_CTYPE_H
# include <ctype.h>
#endif
#ifdef HAVE_ARPA_INET_H
# include <arpa/inet.h>
#endif
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif
#ifdef HAVE_RULI_H
# include <ruli.h>
#endif
#ifdef HAVE_ERRNO_H
# include <errno.h>
#endif
#ifdef HAVE_CARES_H
# ifdef HAVE_ARPA_NAMESER_H
# include <arpa/nameser.h>
# endif
# include <ares.h>
# ifndef NS_RRFIXEDSZ
# define NS_RRFIXEDSZ 10
# define NS_QFIXEDSZ 4
# define NS_HFIXEDSZ 12
# endif
int caport;
unsigned long caadr;
char *ca_tmpname;
ares_channel channel;
#endif // HAVE_CARES_H
#include "helper.h"
#include "exit_code.h"
/* returns 1 if the string an IP address otherwise zero */
int is_ip(char *str) {
int i = 0;
int dotcount = 0;
/*try understanding if this is a valid ip address
we are skipping the values of the octets specified here.
for instance, this code will allow 952.0.320.567 through*/
while (*str != '\0')
{
for (i = 0; i < 3; i++, str++)
if (isdigit((int)*str) == 0)
break;
if (*str != '.')
break;
str++;
dotcount++;
}
/* three dots with upto three digits in before, between and after ? */
if (dotcount == 3 && i > 0 && i <= 3)
return 1;
else
return 0;
}
/* take either a dot.decimal string of ip address or a
domain name and returns a NETWORK ordered long int containing
the address. i chose to internally represent the address as long for speedier
comparisions.
any changes to getaddress have to be patched back to the net library.
contact: farhan@hotfoon.com
returns zero if there is an error.
this is convenient as 0 means 'this' host and the traffic of
a badly behaving dns system remains inside (you send to 0.0.0.0)
*/
unsigned long getaddress(char *host) {
struct hostent* pent;
long l, *lp;
if (is_ip(host))
return inet_addr(host);
/* try the system's own resolution mechanism for dns lookup:
required only for domain names.
inspite of what the rfc2543 :D Using SRV DNS Records recommends,
we are leaving it to the operating system to do the name caching.
this is an important implementational issue especially in the light
dynamic dns servers like dynip.com or dyndns.com where a dial
ip address is dynamically assigned a sub domain like farhan.dynip.com
although expensive, this is a must to allow OS to take
the decision to expire the DNS records as it deems fit.
*/
pent = gethostbyname(host);
if (!pent) {
printf("'%s' is unresolveable\n", host);
exit_code(2);
}
lp = (long *) (pent->h_addr);
l = *lp;
return l;
}
#ifdef HAVE_CARES_H
static const unsigned char *parse_rr(const unsigned char *aptr, const unsigned char *abuf, int alen) {
char *name;
long len;
int status, type, dnsclass, dlen;
struct in_addr addr;
#ifdef DEBUG
printf("ca_tmpname: %s\n", ca_tmpname);
#endif
status = ares_expand_name(aptr, abuf, alen, &name, &len);
if (status != ARES_SUCCESS) {
printf("error: failed to expand query name\n");
exit_code(2);
}
aptr += len;
if (aptr + NS_RRFIXEDSZ > abuf + alen) {
printf("error: not enough data in DNS answer 1\n");
free(name);
return NULL;
}
type = DNS_RR_TYPE(aptr);
dnsclass = DNS_RR_CLASS(aptr);
dlen = DNS_RR_LEN(aptr);
aptr += NS_RRFIXEDSZ;
if (aptr + dlen > abuf + alen) {
printf("error: not enough data in DNS answer 2\n");
free(name);
return NULL;
}
if (dnsclass != CARES_CLASS_C_IN) {
printf("error: unsupported dnsclass (%i) in DNS answer\n", dnsclass);
free(name);
return NULL;
}
if ((ca_tmpname == NULL && type != CARES_TYPE_SRV) ||
(ca_tmpname != NULL &&
(type != CARES_TYPE_A && type != CARES_TYPE_CNAME))) {
printf("error: unsupported DNS response type (%i)\n", type);
free(name);
return NULL;
}
if (type == CARES_TYPE_SRV) {
free(name);
caport = DNS__16BIT(aptr + 4);
#ifdef DEBUG
printf("caport: %i\n", caport);
#endif
status = ares_expand_name(aptr + 6, abuf, alen, &name, &len);
if (status != ARES_SUCCESS) {
printf("error: failed to expand SRV name\n");
return NULL;
}
#ifdef DEBUG
printf("SRV name: %s\n", name);
#endif
if (is_ip(name)) {
caadr = inet_addr(name);
free(name);
}
else {
ca_tmpname = name;
}
}
else if (type == CARES_TYPE_CNAME) {
if (STRNCASECMP(ca_tmpname, name, strlen(ca_tmpname)) == 0) {
ca_tmpname = malloc(strlen(name));
if (ca_tmpname == NULL) {
printf("error: failed to allocate memory\n");
exit_code(2);
}
strcpy(ca_tmpname, name);
}
free(name);
}
else if (type == CARES_TYPE_A) {
if (dlen == 4 && STRNCASECMP(ca_tmpname, name, strlen(ca_tmpname)) == 0) {
memcpy(&addr, aptr, sizeof(struct in_addr));
caadr = addr.s_addr;
}
free(name);
}
return aptr + dlen;
}
static const unsigned char *skip_rr(const unsigned char *aptr, const unsigned char *abuf, int alen) {
int status, dlen;
long len;
char *name;
#ifdef DEBUG
printf("skipping rr section...\n");
#endif
status = ares_expand_name(aptr, abuf, alen, &name, &len);
aptr += len;
dlen = DNS_RR_LEN(aptr);
aptr += NS_RRFIXEDSZ;
aptr += dlen;
free(name);
return aptr;
}
static const unsigned char *skip_query(const unsigned char *aptr, const unsigned char *abuf, int alen) {
int status;
long len;
char *name;
#ifdef DEBUG
printf("skipping query section...\n");
#endif
status = ares_expand_name(aptr, abuf, alen, &name, &len);
aptr += len;
aptr += NS_QFIXEDSZ;
free(name);
return aptr;
}
static void cares_callback(void *arg, int status, unsigned char *abuf, int alen) {
int i;
unsigned int ancount, nscount, arcount;
const unsigned char *aptr;
#ifdef DEBUG
printf("cares_callback: status=%i, alen=%i\n", status, alen);
#endif
if (status != ARES_SUCCESS) {
if (verbose > 1)
printf("ares failed: %s\n", ares_strerror(status));
return;
}
ancount = DNS_HEADER_ANCOUNT(abuf);
nscount = DNS_HEADER_NSCOUNT(abuf);
arcount = DNS_HEADER_ARCOUNT(abuf);
#ifdef DEBUG
printf("ancount: %i, nscount: %i, arcount: %i\n", ancount, nscount, arcount);
#endif
/* safety check */
if (alen < NS_HFIXEDSZ)
return;
aptr = abuf + NS_HFIXEDSZ;
aptr = skip_query(aptr, abuf, alen);
for (i = 0; i < ancount && caadr == 0; i++) {
if (ca_tmpname == NULL)
aptr = parse_rr(aptr, abuf, alen);
else
aptr = skip_rr(aptr, abuf, alen);
}
if (caadr == 0) {
for (i = 0; i < nscount; i++) {
aptr = skip_rr(aptr, abuf, alen);
}
for (i = 0; i < arcount && caadr == 0; i++) {
aptr = parse_rr(aptr, abuf, alen);
}
}
}
inline unsigned long srv_ares(char *host, int *port, char *srv) {
int nfds, count, srvh_len;
char *srvh;
fd_set read_fds, write_fds;
struct timeval *tvp, tv;
caport = 0;
caadr = 0;
ca_tmpname = NULL;
#ifdef DEBUG
printf("!!! ARES query !!!\n");
#endif
srvh_len = strlen(host) + strlen(srv) + 2;
srvh = malloc(srvh_len);
if (srvh == NULL) {
printf("error: failed to allocate memory (%i) for ares query\n", srvh_len);
exit_code(2);
}
memset(srvh, 0, srvh_len);
strncpy(srvh, srv, strlen(srv));
memcpy(srvh + strlen(srv), ".", 1);
strcpy(srvh + strlen(srv) + 1, host);
#ifdef DEBUG
printf("hostname: '%s', len: %i\n", srvh, srvh_len);
#endif
ares_query(channel, srvh, CARES_CLASS_C_IN, CARES_TYPE_SRV, cares_callback, (char *) NULL);
#ifdef DEBUG
printf("after ares_query\n");
#endif
/* wait for query to complete */
while (1) {
FD_ZERO(&read_fds);
FD_ZERO(&write_fds);
nfds = ares_fds(channel, &read_fds, &write_fds);
if (nfds == 0)
break;
tvp = ares_timeout(channel, NULL, &tv);
count = select(nfds, &read_fds, &write_fds, NULL, tvp);
if (count < 0 && errno != EINVAL) {
perror("ares select");
exit_code(2);
}
ares_process(channel, &read_fds, &write_fds);
}
#ifdef DEBUG
printf("end of while\n");
#endif
*port = caport;
if (caadr == 0 && ca_tmpname != NULL) {
caadr = getaddress(ca_tmpname);
}
if (ca_tmpname != NULL)
free(ca_tmpname);
free(srvh);
return caadr;
}
#endif // HAVE_CARES_H
#ifdef HAVE_RULI_H
inline unsigned long srv_ruli(char *host, int *port, char *srv) {
int srv_code;
int ruli_opts = RULI_RES_OPT_SEARCH | RULI_RES_OPT_SRV_NOINET6 | RULI_RES_OPT_SRV_NOSORT6 | RULI_RES_OPT_SRV_NOFALL;
#ifdef RULI_RES_OPT_SRV_CNAME
ruli_opts |= RULI_RES_OPT_SRV_CNAME;
#endif
ruli_sync_t *sync_query = ruli_sync_query(srv, host, *port, ruli_opts);
/* sync query failure? */
if (!sync_query) {
printf("DNS SRV lookup failed for: %s\n", host);
exit_code(2);
}
srv_code = ruli_sync_srv_code(sync_query);
/* timeout? */
if (srv_code == RULI_SRV_CODE_ALARM) {
printf("Timeout during DNS SRV lookup for: %s\n", host);
ruli_sync_delete(sync_query);
exit_code(2);
}
/* service provided? */
else if (srv_code == RULI_SRV_CODE_UNAVAILABLE) {
printf("SRV service not provided for: %s\n", host);
ruli_sync_delete(sync_query);
exit_code(2);
}
else if (srv_code) {
int rcode = ruli_sync_rcode(sync_query);
if (verbose > 1)
printf("SRV query failed for: %s, srv_code=%d, rcode=%d\n", host, srv_code, rcode);
ruli_sync_delete(sync_query);
return 0;
}
ruli_list_t *srv_list = ruli_sync_srv_list(sync_query);
int srv_list_size = ruli_list_size(srv_list);
if (srv_list_size < 1) {
if (verbose > 1)
printf("No SRV record: %s.%s\n", srv, host);
return 0;
}
ruli_srv_entry_t *entry = (ruli_srv_entry_t *) ruli_list_get(srv_list, 0);
ruli_list_t *addr_list = &entry->addr_list;
int addr_list_size = ruli_list_size(addr_list);
if (addr_list_size < 1) {
printf("missing addresses in SRV lookup for: %s\n", host);
ruli_sync_delete(sync_query);
exit_code(2);
}
*port = entry->port;
ruli_addr_t *addr = (ruli_addr_t *) ruli_list_get(addr_list, 0);
return addr->addr.ipv4.s_addr;
}
#endif // HAVE_RULI_H
unsigned long getsrvaddress(char *host, int *port, char *srv) {
#ifdef HAVE_RULI_H
return srv_ruli(host, port, srv);
#else
# ifdef HAVE_CARES_H // HAVE_RULI_H
return srv_ares(host, port, srv);
# else // HAVE_CARES_H
return 0;
# endif
#endif
}
/* Finds the SRV records for the given host. It returns the target IP
* address and fills the port and transport if a suitable SRV record
* exists. Otherwise it returns 0. The function follows 3263: first
* TLS, then TCP and finally UDP. */
unsigned long getsrvadr(char *host, int *port, unsigned int *transport) {
unsigned long adr = 0;
#ifdef HAVE_SRV
int srvport = 5060;
#ifdef HAVE_CARES_H
int status;
int optmask = ARES_OPT_FLAGS;
struct ares_options options;
options.flags = ARES_FLAG_NOCHECKRESP;
options.servers = NULL;
options.nservers = 0;
status = ares_init_options(&channel, &options, optmask);
if (status != ARES_SUCCESS) {
printf("error: failed to initialize ares\n");
exit_code(2);
}
#endif
#ifdef WITH_TLS_TRANSP
adr = getsrvaddress(host, &srvport, SRV_SIP_TLS);
if (adr != 0) {
*transport = SIP_TLS_TRANSPORT;
if (verbose > 1)
printf("using SRV record: %s.%s:%i\n", SRV_SIP_TLS, host, srvport);
printf("TLS transport not yet supported\n");
exit_code(2);
}
else {
#endif
adr = getsrvaddress(host, &srvport, SRV_SIP_TCP);
if (adr != 0) {
*transport = SIP_TCP_TRANSPORT;
if (verbose > 1)
printf("using SRV record: %s.%s:%i\n", SRV_SIP_TCP, host, srvport);
}
else {
adr = getsrvaddress(host, &srvport, SRV_SIP_UDP);
if (adr != 0) {
*transport = SIP_UDP_TRANSPORT;
if (verbose > 1)
printf("using SRV record: %s.%s:%i\n", SRV_SIP_UDP, host, srvport);
}
}
#ifdef WITH_TLS_TRANSP
}
#endif
#ifdef HAVE_CARES_H
ares_destroy(channel);
#endif
*port = srvport;
#endif // HAVE_SRV
return adr;
}
/* because the full qualified domain name is needed by many other
functions it will be determined by this function.
*/
void get_fqdn(){
char hname[100], dname[100], hlp[18];
size_t namelen=100;
struct hostent* he;
struct utsname un;
memset(&hname, 0, sizeof(hname));
memset(&dname, 0, sizeof(dname));
memset(&hlp, 0, sizeof(hlp));
if (hostname) {
strncpy(fqdn, hostname, FQDN_SIZE);
strncpy(hname, hostname, 100);
}
else {
if ((uname(&un))==0) {
strncpy(hname, un.nodename, 100);
}
else {
if (gethostname(&hname[0], namelen) < 0) {
fprintf(stderr, "error: cannot determine hostname\n");
exit_code(2);
}
}
#ifdef HAVE_GETDOMAINNAME
/* a hostname with dots should be a domainname */
if ((strchr(hname, '.'))==NULL) {
if (getdomainname(&dname[0], namelen) < 0) {
fprintf(stderr, "error: cannot determine domainname\n");
exit_code(2);
}
if (strcmp(&dname[0],"(none)")!=0)
snprintf(fqdn, FQDN_SIZE, "%s.%s", hname, dname);
}
else {
strncpy(fqdn, hname, FQDN_SIZE);
}
#endif
}
if (!(numeric == 1 && is_ip(fqdn))) {
he=gethostbyname(hname);
if (he) {
if (numeric == 1) {
snprintf(hlp, 15, "%s", inet_ntoa(*(struct in_addr *) he->h_addr_list[0]));
strncpy(fqdn, hlp, FQDN_SIZE);
}
else {
if ((strchr(he->h_name, '.'))!=NULL && (strchr(hname, '.'))==NULL) {
strncpy(fqdn, he->h_name, FQDN_SIZE);
}
else {
strncpy(fqdn, hname, FQDN_SIZE);
}
}
}
else {
fprintf(stderr, "error: cannot resolve local hostname: %s\n", hname);
exit_code(2);
}
}
if ((strchr(fqdn, '.'))==NULL) {
if (hostname) {
fprintf(stderr, "warning: %s is not resolvable... continouing anyway\n", fqdn);
strncpy(fqdn, hostname, FQDN_SIZE);
}
else {
fprintf(stderr, "error: this FQDN or IP is not valid: %s\n", fqdn);
exit_code(2);
}
}
if (verbose > 2)
printf("fqdnhostname: %s\n", fqdn);
}
/* this function searches for search in mess and replaces it with
replacement */
void replace_string(char *mess, char *search, char *replacement){
char *backup, *insert;
insert=STRCASESTR(mess, search);
if (insert==NULL){
if (verbose > 2)
fprintf(stderr, "warning: could not find this '%s' replacement string in "
"message\n", search);
}
else {
while (insert){
backup=str_alloc(strlen(insert)+1);
strcpy(backup, insert+strlen(search));
strcpy(insert, replacement);
strcpy(insert+strlen(replacement), backup);
free(backup);
insert=STRCASESTR(mess, search);
}
}
}
/* checks if the strings contains special double marks and then
* replace all occurences of this strings in the message */
void replace_strings(char *mes, char *strings) {
char *pos, *atr, *val, *repl, *end;
char sep;
pos=atr=val=repl = NULL;
#ifdef DEBUG
printf("replace_strings entered\nstrings: '%s'\n", strings);
#endif
if ((isalnum(*strings) != 0) &&
(isalnum(*(strings + strlen(strings) - 1)) != 0)) {
replace_string(req, "$replace$", replace_str);
}
else {
sep = *strings;
#ifdef DEBUG
printf("sep: '%c'\n", sep);
#endif
end = strings + strlen(strings);
pos = strings + 1;
while (pos < end) {
atr = pos;
pos = strchr(atr, sep);
if (pos != NULL) {
*pos = '\0';
val = pos + 1;
pos = strchr(val, sep);
if (pos != NULL) {
*pos = '\0';
pos++;
}
}
#ifdef DEBUG
printf("atr: '%s'\nval: '%s'\n", atr, val);
#endif
if ((atr != NULL) && (val != NULL)) {
repl = str_alloc(strlen(val) + 3);
if (repl == NULL) {
printf("failed to allocate memory\n");
exit_code(2);
}
sprintf(repl, "$%s$", atr);
replace_string(mes, repl, val);
free(repl);
}
#ifdef DEBUG
printf("pos: '%s'\n", pos);
#endif
}
}
#ifdef DEBUG
printf("mes:\n'%s'\n", mes);
#endif
}
/* insert \r in front of all \n if it is not present allready */
void insert_cr(char *mes){
char *lf, *pos, *backup;
pos = mes;
lf = strchr(pos, '\n');
while ((lf != NULL) && (*(--lf) != '\r')) {
backup=str_alloc(strlen(lf)+2);
strcpy(backup, lf+1);
*(lf+1) = '\r';
strcpy(lf+2, backup);
free(backup);
pos = lf+3;
lf = strchr(pos, '\n');
}
lf = STRCASESTR(mes, "\r\n\r\n");
if (lf == NULL) {
lf = mes + strlen(mes);
sprintf(lf, "\r\n");
}
}
/* sipmly swappes the content of the two buffers */
void swap_buffers(char *fst, char *snd) {
char *tmp;
if (fst == snd)
return;
tmp = str_alloc(strlen(fst)+1);
strcpy(tmp, fst);
strcpy(fst, snd);
strcpy(snd, tmp);
free(tmp);
}
void swap_ptr(char **fst, char **snd)
{
char *tmp;
tmp = *fst;
*fst = *snd;
*snd = tmp;
}
/* trashes one character in buff randomly */
void trash_random(char *message)
{
int r;
float t;
char *position;
t=(float)rand()/RAND_MAX;
r=(int)(t * (float)strlen(message));
position=message+r;
r=(int)(t*(float)255);
*position=(char)r;
if (verbose > 2)
printf("request:\n%s\n", message);
}
/* this function is taken from traceroute-1.4_p12
which is distributed under the GPL and it returns
the difference between to timeval structs */
double deltaT(struct timeval *t1p, struct timeval *t2p)
{
register double dt;
dt = (double)(t2p->tv_sec - t1p->tv_sec) * 1000.0 +
(double)(t2p->tv_usec - t1p->tv_usec) / 1000.0;
return (dt);
}
/* returns one if the string contains only numbers otherwise zero */
int is_number(char *number)
{
int digit = 1;
while (digit && (*number != '\0')) {
digit = isdigit(*number);
number++;
}
return digit;
}
/* tries to convert the given string into an integer. it strips
* white-spaces and exits if an error happens */
int str_to_int(char *num)
{
int ret;
#ifdef HAVE_STRTOL
errno = 0;
ret = strtol(num, NULL, 10);
if (errno == EINVAL || errno == ERANGE) {
printf("%s\n", num);
perror("integer converting error");
exit_code(2);
}
#else
char backup;
int len = strlen(num);
char *start = num;
char *end = num + len;
while (!isdigit(*start) && isspace(*start) && start < end)
start++;
end = start;
end++;
while (end < num + len && *end != '\0' && !isspace(*end))
end++;
backup = *end;
*end = '\0';
if (!is_number(start)) {
fprintf(stderr, "error: string is not a number: %s\n", start);
exit_code(2);
}
ret = atoi(start);
*end = backup;
if (ret <= 0) {
fprintf(stderr, "error: failed to convert string to integer: %s\n", num);
exit_code(2);
}
#endif
return ret;
}
/* reads into the given buffer from standard input until the EOF
* character, LF character or the given size of the buffer is exceeded */
int read_stdin(char *buf, int size, int ret)
{
int i, j;
for(i = 0; i < size - 1; i++) {
j = getchar();
if (((ret == 0) && (j == EOF)) ||
((ret == 1) && (j == '\n'))) {
*(buf + i) = '\0';
return i;
}
else {
*(buf + i) = j;
}
}
*(buf + i) = '\0';
if (verbose)
fprintf(stderr, "warning: readin buffer size exceeded\n");
return i;
}
/* tries to allocate the given size of memory and sets it all to zero.
* if the allocation fails it exits */
void *str_alloc(size_t size)
{
char *ptr;
#ifdef HAVE_CALLOC
ptr = calloc(1, size);
#else
ptr = malloc(size);
#endif
if (ptr == NULL) {
fprintf(stderr, "error: memory allocation failed\n");
exit_code(255);
}
#ifndef HAVE_CALLOC
memset(ptr, 0, size);
#endif
return ptr;
}

@ -0,0 +1,92 @@
/*
* $Id: helper.h 397 2006-01-28 21:11:50Z calrissian $
*
* Copyright (C) 2002-2004 Fhg Fokus
* Copyright (C) 2004-2005 Nils Ohlmeier
*
* This file belongs to sipsak, a free sip testing tool.
*
* sipsak 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.
*
* sipsak 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.
*/
#ifndef SIPSAK_HELPER_H
#define SIPSAK_HELPER_H
#include "sipsak.h"
#ifdef HAVE_SYS_TIME_H
# include <sys/time.h>
#else
# include <time.h>
#endif
#ifdef HAVE_SYS_SELECT_H
# include <sys/socket.h>
#endif
#ifdef HAVE_CARES_H
# define HAVE_SRV
#else
# ifdef HAVE_RULI_H
# define HAVE_SRV
# endif
#endif
#ifdef HAVE_CARES_H
# define CARES_TYPE_A 1
# define CARES_TYPE_CNAME 5
# define CARES_TYPE_SRV 33
# define CARES_CLASS_C_IN 1
/* copied from ares_dns.h */
# define DNS__16BIT(p) (((p)[0] << 8) | (p)[1])
# define DNS_HEADER_ANCOUNT(h) DNS__16BIT((h) + 6)
# define DNS_HEADER_NSCOUNT(h) DNS__16BIT((h) + 8)
# define DNS_HEADER_ARCOUNT(h) DNS__16BIT((h) + 10)
# define DNS_RR_TYPE(r) DNS__16BIT(r)
# define DNS_RR_CLASS(r) DNS__16BIT((r) + 2)
# define DNS_RR_LEN(r) DNS__16BIT((r) + 8)
#endif
#ifdef HAVE_SRV
# define SRV_SIP_TLS "_sip._tls"
# define SRV_SIP_TCP "_sip._tcp"
# define SRV_SIP_UDP "_sip._udp"
#endif
int is_ip(char *str);
unsigned long getaddress(char *host);
unsigned long getsrvadr(char *host, int *port, unsigned int *transport);
void get_fqdn();
void replace_string(char *mes, char *search, char *replacement);
void replace_strings(char *mes, char *strings);
void insert_cr(char *mes);
void swap_buffers(char *fst, char *snd);
void swap_ptr(char **fst, char **snd);
void trash_random(char *message);
double deltaT(struct timeval *t1p, struct timeval *t2p);
int is_number(char *number);
int str_to_int(char *num);
int read_stdin(char *buf, int size, int ret);
void *str_alloc(size_t size);
#endif

@ -0,0 +1,325 @@
#!/bin/sh
# install - install a program, script, or datafile
scriptversion=2004-04-01.17
# 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}"
transformbasename=
transform_arg=
instcmd="$mvprog"
chmodcmd="$chmodprog 0755"
chowncmd=
chgrpcmd=
stripcmd=
rmcmd="$rmprog -f"
mvcmd="$mvprog"
src=
dst=
dir_arg=
usage="Usage: $0 [OPTION]... SRCFILE DSTFILE
or: $0 [OPTION]... SRCFILES... DIRECTORY
or: $0 -d DIRECTORIES...
In the first form, install SRCFILE to DSTFILE, removing SRCFILE by default.
In the second, create the directory path DIR.
Options:
-b=TRANSFORMBASENAME
-c copy source (using $cpprog) instead of moving (using $mvprog).
-d create directories instead of installing files.
-g GROUP $chgrp installed files to GROUP.
-m MODE $chmod installed files to MODE.
-o USER $chown installed files to USER.
-s strip installed files (using $stripprog).
-t=TRANSFORM
--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
-b=*) transformbasename=`echo $1 | sed 's/-b=//'`
shift
continue;;
-c) instcmd=$cpprog
shift
continue;;
-d) dir_arg=true
shift
continue;;
-g) chgrpcmd="$chgrpprog $2"
shift
shift
continue;;
--help) echo "$usage"; exit 0;;
-m) chmodcmd="$chmodprog $2"
shift
shift
continue;;
-o) chowncmd="$chownprog $2"
shift
shift
continue;;
-s) stripcmd=$stripprog
shift
continue;;
-t=*) transformarg=`echo $1 | sed 's/-t=//'`
shift
continue;;
--version) echo "$0 $scriptversion"; exit 0;;
*) # When -d is used, all remaining arguments are directories to create.
test -n "$dir_arg" && 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
instcmd=:
chmodcmd=
else
instcmd=$mkdirprog
fi
else
# Waiting for this to be detected by the "$instcmd $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
dst=$dst/`basename "$src"`
fi
fi
# This sed command emulates the dirname command.
dstdir=`echo "$dst" | sed -e '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 - `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'`
IFS=$oIFS
pathcomp=
while test $# -ne 0 ; do
pathcomp=$pathcomp$1
shift
if test ! -d "$pathcomp"; then
$mkdirprog "$pathcomp" || lasterr=$?
# 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 ${lasterr-1}); exit; }
fi
pathcomp=$pathcomp/
done
fi
if test -n "$dir_arg"; then
$doit $instcmd "$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
# If we're going to rename the final executable, determine the name now.
if test -z "$transformarg"; then
dstfile=`basename "$dst"`
else
dstfile=`basename "$dst" $transformbasename \
| sed $transformarg`$transformbasename
fi
# don't allow the sed command to completely eliminate the filename.
test -z "$dstfile" && 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 'status=$?; rm -f "$dsttmp" "$rmtmp" && exit $status' 0
trap '(exit $?); exit' 1 2 13 15
# Move or copy the file name to the temp name
$doit $instcmd "$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 $instcmd $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
}
else
:
fi
} &&
# Now rename the file to the real destination.
$doit $mvcmd "$dsttmp" "$dstdir/$dstfile"
}
}
fi || { (exit 1); exit; }
done
# The final little trick to "correctly" pass the exit status to the exit trap.
{
(exit 0); exit
}
# 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:

364
md5.c

@ -0,0 +1,364 @@
/*
$Id: md5.c 397 2006-01-28 21:11:50Z calrissian $
MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
rights reserved.
License to copy and use this software is granted provided that it
is identified as the "RSA Data Security, Inc. MD5 Message-Digest
Algorithm" in all material mentioning or referencing this software
or this function.
License is also granted to make and use derivative works provided
that such works are identified as "derived from the RSA Data
Security, Inc. MD5 Message-Digest Algorithm" in all material
mentioning or referencing the derived work.
RSA Data Security, Inc. makes no representations concerning either
the merchantability of this software or the suitability of this
software for any particular purpose. It is provided "as is"
without express or implied warranty of any kind.
These notices must be retained in any copies of any part of this
documentation and/or software.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "md5.h"
#ifndef HAVE_EXTERNAL_MD5
#ifdef HAVE_STRING_H
# include <string.h>
#endif
#define USE_MEM
/* Constants for MD5Transform routine.
*/
#define S11 7
#define S12 12
#define S13 17
#define S14 22
#define S21 5
#define S22 9
#define S23 14
#define S24 20
#define S31 4
#define S32 11
#define S33 16
#define S34 23
#define S41 6
#define S42 10
#define S43 15
#define S44 21
static void MD5Transform PROTO_LIST ((UINT4 [4], unsigned char [64]));
static void Encode PROTO_LIST
((unsigned char *, UINT4 *, unsigned int));
static void Decode PROTO_LIST
((UINT4 *, unsigned char *, unsigned int));
static void MD5_memcpy PROTO_LIST ((POINTER, POINTER, unsigned int));
static void MD5_memset PROTO_LIST ((POINTER, int, unsigned int));
static unsigned char PADDING[64] = {
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
/* F, G, H and I are basic MD5 functions.
*/
#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
#define H(x, y, z) ((x) ^ (y) ^ (z))
#define I(x, y, z) ((y) ^ ((x) | (~z)))
/* ROTATE_LEFT rotates x left n bits.
*/
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
Rotation is separate from addition to prevent recomputation.
*/
#define FF(a, b, c, d, x, s, ac) { \
(a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
#define GG(a, b, c, d, x, s, ac) { \
(a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
#define HH(a, b, c, d, x, s, ac) { \
(a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
#define II(a, b, c, d, x, s, ac) { \
(a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
/* MD5 initialization. Begins an MD5 operation, writing a new context.
*/
void MD5Init (context)
MD5_CTX *context; /* context */
{
context->count[0] = context->count[1] = 0;
/* Load magic initialization constants.
*/
context->state[0] = 0x67452301;
context->state[1] = 0xefcdab89;
context->state[2] = 0x98badcfe;
context->state[3] = 0x10325476;
}
/* MD5 block update operation. Continues an MD5 message-digest
operation, processing another message block, and updating the
context.
*/
void MD5Update (context, input, inputLen)
MD5_CTX *context; /* context */
unsigned char *input; /* input block */
unsigned int inputLen; /* length of input block */
{
unsigned int i, index, partLen;
/* Compute number of bytes mod 64 */
index = (unsigned int)((context->count[0] >> 3) & 0x3F);
/* Update number of bits */
if ((context->count[0] += ((UINT4)inputLen << 3))
< ((UINT4)inputLen << 3))
context->count[1]++;
context->count[1] += ((UINT4)inputLen >> 29);
partLen = 64 - index;
/* Transform as many times as possible.
*/
if (inputLen >= partLen) {
MD5_memcpy
((POINTER)&context->buffer[index], (POINTER)input, partLen);
MD5Transform (context->state, context->buffer);
for (i = partLen; i + 63 < inputLen; i += 64)
MD5Transform (context->state, &input[i]);
index = 0;
}
else
i = 0;
/* Buffer remaining input */
MD5_memcpy
((POINTER)&context->buffer[index], (POINTER)&input[i],
inputLen-i);
}
/* MD5 finalization. Ends an MD5 message-digest operation, writing the
the message digest and zeroizing the context.
*/
void MD5Final (digest, context)
unsigned char digest[16]; /* message digest */
MD5_CTX *context; /* context */
{
unsigned char bits[8];
unsigned int index, padLen;
/* Save number of bits */
Encode (bits, context->count, 8);
/* Pad out to 56 mod 64.
*/
index = (unsigned int)((context->count[0] >> 3) & 0x3f);
padLen = (index < 56) ? (56 - index) : (120 - index);
MD5Update (context, PADDING, padLen);
/* Append length (before padding) */
MD5Update (context, bits, 8);
/* Store state in digest */
Encode (digest, context->state, 16);
/* Zeroize sensitive information.
*/
MD5_memset ((POINTER)context, 0, sizeof (*context));
}
/* MD5 basic transformation. Transforms state based on block.
*/
static void MD5Transform (state, block)
UINT4 state[4];
unsigned char block[64];
{
UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
Decode (x, block, 64);
/* Round 1 */
FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
/* Round 2 */
GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */
GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
/* Round 3 */
HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */
HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
/* Round 4 */
II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
state[0] += a;
state[1] += b;
state[2] += c;
state[3] += d;
/* Zeroize sensitive information.
*/
MD5_memset ((POINTER)x, 0, sizeof (x));
}
/* Encodes input (UINT4) into output (unsigned char). Assumes len is
a multiple of 4.
*/
static void Encode (output, input, len)
unsigned char *output;
UINT4 *input;
unsigned int len;
{
unsigned int i, j;
for (i = 0, j = 0; j < len; i++, j += 4) {
output[j] = (unsigned char)(input[i] & 0xff);
output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
}
}
/* Decodes input (unsigned char) into output (UINT4). Assumes len is
a multiple of 4.
*/
static void Decode (output, input, len)
UINT4 *output;
unsigned char *input;
unsigned int len;
{
unsigned int i, j;
for (i = 0, j = 0; j < len; i++, j += 4)
output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) |
(((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24);
}
/* Note: Replace "for loop" with standard memcpy if possible.
*/
static void MD5_memcpy (output, input, len)
POINTER output;
POINTER input;
unsigned int len;
{
#ifndef USE_MEM
unsigned int i;
for (i = 0; i < len; i++)
output[i] = input[i];
#else
memcpy( output, input, len );
#endif
}
/* Note: Replace "for loop" with standard memset if possible.
*/
static void MD5_memset (output, value, len)
POINTER output;
int value;
unsigned int len;
{
#ifndef USE_MEM
unsigned int i;
for (i = 0; i < len; i++)
((char *)output)[i] = (char)value;
#else
memset( output, value, len );
#endif
}
#endif /* ! HAVE_EXTERNAL_MD5 */

63
md5.h

@ -0,0 +1,63 @@
/* MD5.H - header file for MD5C.C
* $Id: md5.h 397 2006-01-28 21:11:50Z calrissian $
*/
/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
rights reserved.
License to copy and use this software is granted provided that it
is identified as the "RSA Data Security, Inc. MD5 Message-Digest
Algorithm" in all material mentioning or referencing this software
or this function.
License is also granted to make and use derivative works provided
that such works are identified as "derived from the RSA Data
Security, Inc. MD5 Message-Digest Algorithm" in all material
mentioning or referencing the derived work.
RSA Data Security, Inc. makes no representations concerning either
the merchantability of this software or the suitability of this
software for any particular purpose. It is provided "as is"
without express or implied warranty of any kind.
These notices must be retained in any copies of any part of this
documentation and/or software.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "sipsak.h"
#ifdef HAVE_GNUTLS
# include <gnutls/openssl.h>
#else
# ifdef HAVE_FULL_OPENSSL
# include <openssl/md5.h>
# endif
#endif
#ifdef HAVE_EXTERNAL_MD5
# define MD5Init MD5_Init
# define MD5Update MD5_Update
# define MD5Final MD5_Final
#else
#include "md5global.h"
/* MD5 context. */
typedef struct {
UINT4 state[4]; /* state (ABCD) */
UINT4 count[2]; /* number of bits, modulo 2^64 (lsb first) */
unsigned char buffer[64]; /* input buffer */
} MD5_CTX;
void MD5Init PROTO_LIST ((MD5_CTX *));
void MD5Update PROTO_LIST
((MD5_CTX *, unsigned char *, unsigned int));
void MD5Final PROTO_LIST ((unsigned char [16], MD5_CTX *));
#endif

@ -0,0 +1,33 @@
/* GLOBAL.H - RSAREF types and constants
*
*/
/* PROTOTYPES should be set to one if and only if the compiler supports
function argument prototyping.
The following makes PROTOTYPES default to 0 if it has not already
been defined with C compiler flags.
*/
#ifndef PROTOTYPES
#define PROTOTYPES 0
#endif
/* POINTER defines a generic pointer type */
typedef unsigned char *POINTER;
/* UINT2 defines a two byte word */
typedef unsigned short int UINT2;
/* UINT4 defines a four byte word */
typedef unsigned long int UINT4;
/* PROTO_LIST is defined depending on how PROTOTYPES is defined above.
If using PROTOTYPES, then PROTO_LIST returns the list, otherwise it
returns an empty list.
*/
#if PROTOTYPES
#define PROTO_LIST(list) list
#else
#define PROTO_LIST(list) ()
#endif

@ -0,0 +1,360 @@
#! /bin/sh
# Common stub for a few missing GNU programs while installing.
scriptversion=2003-09-02.23
# Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003
# 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
;;
esac
# If it does not exist, or fails to run (possibly an outdated version),
# try to emulate it.
case "$1" in
-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>."
;;
-v|--v|--ve|--ver|--vers|--versi|--versio|--version)
echo "missing $scriptversion (GNU Automake)"
;;
-*)
echo 1>&2 "$0: Unknown \`$1' option"
echo 1>&2 "Try \`$0 --help' for more information"
exit 1
;;
aclocal*)
if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
# We have it, but it failed.
exit 1
fi
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)
if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
# We have it, but it failed.
exit 1
fi
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)
if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
# We have it, but it failed.
exit 1
fi
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*)
if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
# We have it, but it failed.
exit 1
fi
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)
if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
# We have it, but it failed.
exit 1
fi
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)
if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
# We have it, but it failed.
exit 1
fi
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)
if test -z "$run" && (makeinfo --version) > /dev/null 2>&1; then
# We have makeinfo, but it failed.
exit 1
fi
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."
file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'`
if test -z "$file"; then
file=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'`
file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $file`
fi
touch $file
;;
tar)
shift
if test -n "$run"; then
echo 1>&2 "ERROR: \`tar' requires --run"
exit 1
fi
# 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:

@ -0,0 +1,111 @@
#! /bin/sh
# mkinstalldirs --- make directory hierarchy
# Author: Noah Friedman <friedman@prep.ai.mit.edu>
# Created: 1993-05-16
# Public domain
errstatus=0
dirmode=""
usage="\
Usage: mkinstalldirs [-h] [--help] [-m mode] dir ..."
# process command line arguments
while test $# -gt 0 ; do
case $1 in
-h | --help | --h*) # -h for help
echo "$usage" 1>&2
exit 0
;;
-m) # -m PERM arg
shift
test $# -eq 0 && { echo "$usage" 1>&2; exit 1; }
dirmode=$1
shift
;;
--) # stop option processing
shift
break
;;
-*) # unknown option
echo "$usage" 1>&2
exit 1
;;
*) # first non-opt arg
break
;;
esac
done
for file
do
if test -d "$file"; then
shift
else
break
fi
done
case $# in
0) exit 0 ;;
esac
case $dirmode in
'')
if mkdir -p -- . 2>/dev/null; then
echo "mkdir -p -- $*"
exec mkdir -p -- "$@"
fi
;;
*)
if mkdir -m "$dirmode" -p -- . 2>/dev/null; then
echo "mkdir -m $dirmode -p -- $*"
exec mkdir -m "$dirmode" -p -- "$@"
fi
;;
esac
for file
do
set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'`
shift
pathcomp=
for d
do
pathcomp="$pathcomp$d"
case $pathcomp in
-*) pathcomp=./$pathcomp ;;
esac
if test ! -d "$pathcomp"; then
echo "mkdir $pathcomp"
mkdir "$pathcomp" || lasterr=$?
if test ! -d "$pathcomp"; then
errstatus=$lasterr
else
if test ! -z "$dirmode"; then
echo "chmod $dirmode $pathcomp"
lasterr=""
chmod "$dirmode" "$pathcomp" || lasterr=$?
if test ! -z "$lasterr"; then
errstatus=$lasterr
fi
fi
fi
fi
pathcomp="$pathcomp/"
done
done
exit $errstatus
# Local Variables:
# mode: shell-script
# sh-indentation: 2
# End:
# mkinstalldirs ends here

@ -0,0 +1,318 @@
/*
* $Id: request.c 397 2006-01-28 21:11:50Z calrissian $
*
* Copyright (C) 2002-2004 Fhg Fokus
* Copyright (C) 2004-2005 Nils Ohlmeier
*
* This file belongs to sipsak, a free sip testing tool.
*
* sipsak 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.
*
* sipsak 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.
*/
#include "sipsak.h"
#ifdef HAVE_STRING_H
# include <string.h>
#endif
#include "request.h"
#include "exit_code.h"
#include "helper.h"
#include "header_f.h"
/* create a valid sip header for the different modes */
void create_msg(int action, char *req_buff, char *repl_buff, char *username, int cseq){
unsigned int c, d, len;
char *req_buf_begin = req_buff;
if(cseq == 0) {
fprintf(stderr, "error: CSeq 0 is not allowed\n");
exit_code(253);
}
if (req_buff == NULL)
abort();
if (username == NULL)
username = "";
c=(unsigned int)rand();
c+=lport;
d=(unsigned int)rand();
switch (action){
case REQ_REG:
sprintf(req_buff,
"%s sip:%s%s"
"%ssip:%s%s;tag=%x\r\n"
"%ssip:%s%s\r\n"
"%s%u@%s\r\n"
"%s%i %s\r\n"
"%s0\r\n"
"%s70\r\n"
"%ssipsak %s\r\n",
REG_STR, domainname, SIP20_STR,
FROM_STR, username, domainname, c,
TO_STR, username, domainname,
CALL_STR, c, fqdn,
CSEQ_STR, cseq, REG_STR,
CON_LEN_STR,
MAX_FRW_STR,
UA_STR, SIPSAK_VERSION);
req_buff += strlen(req_buff);
if (contact_uri!=NULL) {
sprintf(req_buff, "%s%i\r\n"
"%s%s\r\n\r\n",
EXP_STR, expires_t,
CONT_STR, contact_uri);
}
else if (empty_contact == 0) {
sprintf(req_buff, "%s%i\r\n"
"%ssip:%s%s:%i",
EXP_STR, expires_t,
CONT_STR, username, fqdn, lport);
req_buff += strlen(req_buff);
if (transport != SIP_UDP_TRANSPORT)
sprintf(req_buff, "%s%s\r\n\r\n", TRANSPORT_PARAMETER_STR,
transport_str);
else
sprintf(req_buff, "\r\n\r\n");
}
else{
sprintf(req_buff, "\r\n");
}
add_via(req_buf_begin);
break;
case REQ_REM:
sprintf(req_buff,
"%s sip:%s%s"
"%ssip:%s%s;tag=%x\r\n"
"%ssip:%s%s\r\n"
"%s%u@%s\r\n"
"%s%i %s\r\n"
"%s%i\r\n"
"%s0\r\n"
"%s70\r\n"
"%ssipsak %s\r\n"
"%ssip:%s%s:%i;%s0",
REG_STR, domainname, SIP20_STR,
FROM_STR, username, domainname, c,
TO_STR, username, domainname,
CALL_STR, c, fqdn,
CSEQ_STR, cseq, REG_STR,
EXP_STR, expires_t,
CON_LEN_STR,
MAX_FRW_STR,
UA_STR, SIPSAK_VERSION,
CONT_STR, username, fqdn, lport, CON_EXP_STR);
req_buff += strlen(req_buff);
if (transport != SIP_UDP_TRANSPORT) {
sprintf(req_buff, "\r\n\r\n");
}
else {
sprintf(req_buff, "%s%s\r\n\r\n", TRANSPORT_PARAMETER_STR,
transport_str);
}
add_via(req_buf_begin);
break;
case REQ_INV:
sprintf(req_buff,
"%s sip:%s%s%s"
"%ssip:sipsak@%s:%i;tag=%x\r\n"
"%ssip:%s%s\r\n"
"%s%u@%s\r\n"
"%s%i %s\r\n"
"%s0\r\n"
"%ssip:sipsak@%s:%i\r\n"
"%sDONT ANSWER this test call!\r\n"
"%s70\r\n"
"%ssipsak %s\r\n"
"\r\n",
INV_STR, username, domainname, SIP20_STR,
FROM_STR, fqdn, lport, c,
TO_STR, username, domainname,
CALL_STR, c, fqdn,
CSEQ_STR, cseq, INV_STR,
CON_LEN_STR,
CONT_STR, fqdn, lport,
SUB_STR,
MAX_FRW_STR,
UA_STR, SIPSAK_VERSION);
add_via(req_buf_begin);
sprintf(repl_buff,
"%s"
"%ssip:sipsak@%s:%i;tag=%x\r\n"
"%ssip:%s%s;tag=%o%o\r\n"
"%s%u@%s\r\n"
"%s%i %s\r\n"
"%s0\r\n"
"%ssip:sipsak_conf@%s:%i\r\n"
"%ssipsak %s\r\n"
"\r\n",
SIP200_STR,
FROM_STR, fqdn, lport, c,
TO_STR, username, domainname, c, d,
CALL_STR, c, fqdn,
CSEQ_STR, cseq, INV_STR,
CON_LEN_STR,
CONT_STR, fqdn, lport,
UA_STR, SIPSAK_VERSION);
break;
case REQ_MES:
sprintf(req_buff,
"%s sip:%s%s%s"
"%ssip:%s%s\r\n"
"%s%u@%s\r\n"
"%s%i %s\r\n"
"%s%s\r\n"
"%s70\r\n"
"%ssipsak %s\r\n",
MES_STR, username, domainname, SIP20_STR,
TO_STR, username, domainname,
CALL_STR, c, fqdn,
CSEQ_STR, cseq, MES_STR,
CON_TYP_STR, TXT_PLA_STR,
MAX_FRW_STR,
UA_STR, SIPSAK_VERSION);
req_buff += strlen(req_buff);
if (from_uri) {
sprintf(req_buff,
"%s%s;tag=%x\r\n",
FROM_STR, from_uri, c);
}
else {
sprintf(req_buff,
"%ssip:sipsak@%s:%i;tag=%x\r\n",
FROM_STR, fqdn, lport, c);
}
req_buff += strlen(req_buff);
if (mes_body) {
len = strlen(mes_body);
}
else {
len = SIPSAK_MES_STR_LEN + strlen(username);
}
sprintf(req_buff, "%s%u\r\n", CON_LEN_STR, len);
req_buff += strlen(req_buff);
if (con_dis) {
sprintf(req_buff, "%s%s\r\n", CON_DIS_STR, con_dis);
req_buff += strlen(req_buff);
}
sprintf(req_buff, "\r\n");
req_buff += 2;
if (mes_body) {
sprintf(req_buff,
"%s",
mes_body);
}
else {
sprintf(req_buff, "%s%s", SIPSAK_MES_STR, username);
req_buff += strlen(req_buff) - 1;
*(req_buff) = '.';
}
add_via(req_buf_begin);
sprintf(repl_buff,
"%s"
"%ssip:sipsak@%s:%i;tag=%x\r\n"
"%ssip:%s%s;tag=%o%o\r\n"
"%s%u@%s\r\n"
"%s%i %s\r\n"
"%s0\r\n"
"%ssipsak %s\r\n"
"\r\n",
SIP200_STR,
FROM_STR, fqdn, lport, c,
TO_STR, username, domainname, c, d,
CALL_STR, c, fqdn,
CSEQ_STR, cseq, MES_STR,
CON_LEN_STR,
UA_STR, SIPSAK_VERSION);
break;
case REQ_OPT:
sprintf(req_buff,
"%s sip:%s%s%s"
"%ssip:sipsak@%s:%i;tag=%x\r\n"
"%ssip:%s%s\r\n"
"%s%u@%s\r\n"
"%s%i %s\r\n"
"%ssip:sipsak@%s:%i\r\n"
"%s0\r\n"
"%s70\r\n"
"%ssipsak %s\r\n"
"%s%s\r\n"
"\r\n",
OPT_STR, username, domainname, SIP20_STR,
FROM_STR, fqdn, lport, c,
TO_STR, username, domainname,
CALL_STR, c, fqdn,
CSEQ_STR, cseq, OPT_STR,
CONT_STR, fqdn, lport,
CON_LEN_STR,
MAX_FRW_STR,
UA_STR, SIPSAK_VERSION,
ACP_STR, TXT_PLA_STR);
add_via(req_buf_begin);
break;
case REQ_FLOOD:
sprintf(req_buff,
"%s sip:%s%s%s"
"%s%s %s:9;branch=z9hG4bK.%08x\r\n"
"%ssip:sipsak@%s:9;tag=%x\r\n"
"%ssip:%s%s\r\n"
"%s%u@%s\r\n"
"%s%i %s\r\n"
"%ssip:sipsak@%s:9\r\n"
"%s0\r\n"
"%s70\r\n"
"%ssipsak %s\r\n"
"\r\n",
FLOOD_METH, username, domainname, SIP20_STR,
VIA_SIP_STR, TRANSPORT_UDP_STR, fqdn, d,
FROM_STR, fqdn, c,
TO_STR, username, domainname,
CALL_STR, c, fqdn,
CSEQ_STR, cseq, FLOOD_METH,
CONT_STR, fqdn,
CON_LEN_STR,
MAX_FRW_STR,
UA_STR, SIPSAK_VERSION);
break;
case REQ_RAND:
sprintf(req_buff,
"%s sip:%s%s"
"%ssip:sipsak@%s:%i;tag=%x\r\n"
"%ssip:%s\r\n"
"%s%u@%s\r\n"
"%s%i %s\r\n"
"%ssipsak@%s:%i\r\n"
"%s0\r\n"
"%s70\r\n"
"%ssipsak %s\r\n"
"\r\n",
OPT_STR, domainname, SIP20_STR,
FROM_STR, fqdn, lport, c,
TO_STR, domainname,
CALL_STR, c, fqdn,
CSEQ_STR, cseq, OPT_STR,
CONT_STR, fqdn, lport,
CON_LEN_STR,
MAX_FRW_STR,
UA_STR, SIPSAK_VERSION);
add_via(req_buf_begin);
break;
default:
fprintf(stderr, "error: unknown request type to create\n");
exit_code(2);
break;
}
if (headers) {
insert_header(req_buf_begin, headers, 1);
if (repl_buff)
insert_header(repl_buff, headers, 1);
}
}

@ -0,0 +1,25 @@
/*
* $Id: request.h 397 2006-01-28 21:11:50Z calrissian $
*
* Copyright (C) 2002-2004 Fhg Fokus
* Copyright (C) 2004-2005 Nils Ohlmeier
*
* This file belongs to sipsak, a free sip testing tool.
*
* sipsak 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.
*
* sipsak 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.
*/
#ifndef SIPSAK_REQUEST_H
#define SIPSAK_REQUEST_H
void create_msg(int action, char *buff, char *repl_buff, char *username, int cseq);
#endif

1082
shoot.c

File diff suppressed because it is too large Load Diff

@ -0,0 +1,63 @@
/*
* $Id: shoot.h 397 2006-01-28 21:11:50Z calrissian $
*
* Copyright (C) 2002-2004 Fhg Fokus
* Copyright (C) 2004-2005 Nils Ohlmeier
*
* This file belongs to sipsak, a free sip testing tool.
*
* sipsak 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.
*
* sipsak 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.
*/
#ifndef SIPSAK_SHOOT_H
#define SIPSAK_SHOOT_H
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#ifdef HAVE_NETINET_IP_H
# ifdef HAVE_NETINET_IP_ICMP_H
# ifdef HAVE_NETINET_UDP_H
# ifndef HAVE_CYGWIN_ICMP_H
# define RAW_SUPPORT
# endif
# endif
# endif
#endif
#define LPORT_STR_LEN 6
struct sipsak_regexp {
regex_t redexp;
regex_t proexp;
regex_t okexp;
regex_t tmhexp;
regex_t errexp;
regex_t authexp;
regex_t replyexp;
};
enum usteps {
REG_REP,
INV_RECV,
INV_OK_RECV,
INV_ACK_RECV,
MES_RECV,
MES_OK_RECV,
UNREG_REP
};
int inv_trans;
void shoot(char *buff, int buff_size);
#endif

@ -0,0 +1,557 @@
.\" Process this file with
.\" groff -man -Tascii sipsak.1
.\"
.TH SIPSAK 1 "JULY 2002 - SEPTEMBER 2005" Linux "User Manuals"
.SH NAME
sipsak \- a utility for various tests on sip servers and user agents
.SH SYNOPSIS
.B sipsak [-dFGhiILnNMRSTUVvwz] [-a
.I PASSWORD
.B ] [-b
.I NUMBER
.B ] [-c
.I SIPURI
.B ] [-C
.I SIPURI
.B ] [-D
.I NUMBER
.B ] [-e
.I NUMBER
.B ] [-E
.I STRING
.B ] [-f
.I FILE
.B ] [-g
.I STRING
.B ] [-H
.I HOSTNAME
.B ] [-l
.I PORT
.B ] [-m
.I NUMBER
.B ] [-o
.I NUMBER
.B ] [-p
.I HOSTNAME
.B ] [-P
.I NUMBER
.B ] [-q
.I REGEXP
.B ] [-r
.I PORT
.B ] [-t
.I NUMBER
.B ] [-u
.I STRING
.B ] [-W
.I NUMBER
.B ] [-x
.I NUMBER
.B ] -s
.I SIPURI
.SH DESCRIPTION
.B sipsak
is a SIP stress and diagnostics utility.
It sends SIP requests to the server within the
.BR sip-uri
and examines received responses.
It runs in one of the following modes:
.IP "- default mode"
A SIP message is sent to destination in
.BR sip-uri
and reply status is displayed.
The request is either taken from
.BR filename
or generated as a new OPTIONS message.
.IP "- traceroute mode (-T)"
This mode is useful for learning request's path. It
operates similarly to IP-layer utility
.BR traceroute (8).
.IP "- message mode (-M)"
Sends a short message (similar to SMS from the mobile phones) to a given target. With the option
.BR -B
the content of the MESSAGE can be set. Usefull might be the options
.BR -c
and
.BR -O
in this mode.
.IP "- usrloc mode (-U)"
Stress mode for SIP registrar.
.B sipsak
keeps registering to a SIP server at high pace. Additionaly the registrar
can be stressed with the
.BR -I
or the
.BR -M
option.
If
.BR -I
and
.BR -M
are omitted
.B sipsak
can be used to register any given contact (with the
.BR -C
option) for an account at a registrar and to query the current bindings for
an account at a registrar.
.IP "- randtrash mode (-R)"
Parser torture mode.
.B sipsak
keeps sending randomly corrupted messages to torture a SIP server's
parser.
.IP "- flood mode (-F)"
Stress mode for SIP servers.
.B sipsak
keeps sending requests to a SIP server at high pace.
.PP
If libruli (http://www.nongnu.org/ruli/) support is compiled into the
.B sipsak
binary, then first a SRV lookup for _sip._udp.hostname is made. And if this
lookup fails a normal A lookup is made. If a port was given in the target
URI the SRV lookup is omitted. Failover, load distribution and other
transports are not supported yet.
.SH OPTIONS
.IP "-a, --password PASSWORD"
With the given
.I PASSWORD
an authentication will be tryed on received '401 Unauthorized'. Authorization
will be tryed on time. If this option is omitted an authorization with an
empty password ("") will be tryed. If the password is equal to
.I -
the password will be read from the standard input (e.g. the keyboard). This
prevents other users on the same host from seeing the password the password
in the process list.
.B NOTE:
the password still can be read from the memory if other users have access to
it.
.IP "-A, --timing"
prints only the timing values of the test run if verbosity is zero because no
.BR -v
was given. If one or more
.BR -v
were given this option will be ignored.
.IP "-b, --apendix-begin NUMBER"
The starting number which is appended to the user name in the usrloc mode.
This
.I NUMBER
is increased until it reaches the value given by the
.BR -e
parameter. If omitted the starting number will be one.
.IP "-B, --message-body STRING"
The given
.I STRING
will be used as the body for outgoing MESSAGE requests.
.IP "-c, --from SIPURI"
The given
.I SIPURI
will be used in the From header if
.B sipsak
runs in the message mode (initiated with the
.BR -M
option). This is helpfull to present the receiver of a MESSAGE a meaningfull
and usable address to where maybe even responses can be send.
.IP "-C, --contact SIPURI"
This is the content of the Contact header in the usrloc mode. This allows
to insert forwards like for mail. For example you can insert the uri of
your first SIP account at a second account, thus all calls to the second
account will be forwarded to the first account.
As the argument to this option will not be enclosed in brackets you can
give also multiple contacts in the raw format as comma seperated list.
The special words
.B empty
or
.B none
will result in no contact header in the REGISTER request and thus the server
should answer with the current bindings for the account at the registrar.
.IP "-d, --ignore-redirects"
If this option is set all redirects will be ignored. By default without this
option received redirects will be respected. This option is automaticly
activated in the randtrash mode and in the flood mode.
.IP "-D, --timeout-factor NUMBER"
The SIP_T1 timer is getting multiplied with the given NUMBER. After receiving
a provisional response for an INVITE request, or when a reliable transport
like TCP or TLS is used
.B sipsak
waits for the resulting amount of time for a final response until it gives up.
.IP "-e, --appendix-end NUMBER"
The ending number which is appended to the user name in the usrloc mode.
This number is increased until it reaches this ending
.I number.
In the flood mode this is the maximum number of messages which will be send.
If omitted the default value is 2^31 (2147483647) in the flood mode.
.IP "-E, --transport STRING"
The value of
.I STRING
will be used as IP transport for sending and receiving requests and responses.
This option overwrites any result from the URI evaluation and SRV lookup.
Currently only 'udp' and 'tcp' are accepted as value for
.I STRING.
.IP "-f, --filename FILE"
The content of
.I FILE
will be read in in binary mode and will be used as replacement for the
alternatively created sip message. This can used in the default mode to make
other requests than OPTIONS requests (e.g. INVITE). By default missing
carriage returns in front of line feeds will be inserted (use
.BR -L
to de-activate this function). If the filename is equal to
.I -
the file is read from standard input, e.g. from the keyboard or a pipe.
Please note that the manipulation functions (e.g. inserting Via header)
are only tested with RFC conform requests. Additionaly special strings
within the file can be replaced with some local or given values (see
.BR -g
and
.BR -G
for details).
.IP "-F, --flood-mode"
This options activates the flood mode. In this mode OPTIONS requests with
increasing CSeq numbers are sent to the server. Replies are ignored --
source port 9 (discard) of localhost is advertised in topmost Via.
.IP "-h, --help"
Prints out a simple usage help message. If the long option
.BR --help
is available it will print out a help message with the available long options.
.IP "-g, --replace-string STRING"
Activates the replacement of $replace$ within the request (usualy read
in from a file) with the
.I STRING.
Alternatively you can also specify a list of attribute and values.
This list has to start and end with a non alpha-numeric character. The
same character has to be used also as seperator between the attribute and
the value and between new further attribute value pairs. The string
"$attribute$" will be replaced with the value string in the message.
.IP "-G, --replace"
Activates the automatic replacement of the following variables in the
request (usualy read in from a file):
.B $dsthost$
will be replaced by with the host or domainname which is given
by the
.B -s
parameter.
.B $srchost$
will be replaced by the hostname of the local machine.
.B $port$
will be replaced by the local listening port of
.B sipsak.
.B $user$
will be replaced by the username which is given by the
.B -s
parameter.
.IP "-H, --hostname HOSTNAME"
Overwrites the automatic detection of the hostname with the given parameter.
.B Warning:
use this with caution (preferable only if the automatic detection fails).
.IP "-i, --no-via"
Deactivates the insertion of the Via line of the localhost.
.B Warning:
this probably disables the receiving of the responses from the server.
.IP "-I, --invite-mode"
Activates the Invites cycles within the usrloc mode. It should be combined
with
.BR -U.
In this combination
.B sipsak
first registeres a user, and then simulates an
invitation to this user. First an Invite is sent, this is replied with 200 OK
and finaly an ACK is sent. This option can also be used without
.BR -U
, but you should be sure to NOT invite real UAs with this option. In the case
of a missing
.BR -U
the
.BR "-l PORT"
is required because only if you made a
.BR -U
run with a fixed local port before, a run with
.BR -I
and the same fixed local port can be successful.
.B Warning: sipsak
is no real UA and invitations to real UAs can result in unexpected
behaivior.
.IP "-j, --headers STRING"
The
.BR string
will be added as one or more additional headers to the request. The string
"\\n" (note: two characters) will be replaced with CRLF and thus result
in two seperate headers. That way more then one header can be added.
.IP "-l, --local-port PORT"
The receiving UDP socket will use the local network
.I port.
Useful if a file is given by
.BR -f
which contains a correct Via line. Check the
.BR -S
option for details how sipsak sends and receives messages.
.IP "-L, --no-crlf"
De-activates the insertion of carriage returns (\\r) before all line feeds
(\\n) (which is not allready proceeded by carraige return) if the input
is comming from a file (
.BR -f
). Without this option also an empty line will be appended to the request
if required.
.IP "-m, --max-forwards NUMBER"
This sets the value of the Max-Forward header field. If omitted no Max-Forward
field will be inserted. If omitted in the traceroute mode
.BR number
will be 255.
.IP "-M, --message-mode"
This activates the Messages cycles within the usrloc mode (known from
.B sipsak
versions pre 0.8.0 within the normal usrloc test). This option should be
combined with
.BR -U
so that a succesful registration will be tested with a test message to the user
and replied with 200 OK. But this option can also be used without the
.BR -U
option.
.B Warning:
using without
.BR -U
can cause unexpected behaivor.
.IP "-n, --numeric"
Instead of the full qualified domain name in the Via line the IP of the
local host will be used. This option is now on by default.
.IP "-N, --nagios-code"
Use Nagios comliant return codes instead of the normal sipsak ones. This means
.B sipsak
will return 0 if everything was ok and 2 in case of any error (local or remote).
.IP "-o, --sleep NUMBER"
.B sipsak
will sleep for
.BR NUMBER
ms before it starts the next cycle in the usrloc mode. This will slow down
the whole test process to be more realistic. Each cycle will be still completed
as fast as possible, but the whole test will be slowed down.
.IP "-O, --disposition STRING"
The given
.BR STRING
will be used as the content for the Content-Disposition header. Without this
option there will be no Content-Disposition header in the request.
.IP "-p, --outbound-proxy HOSTNAME[:PORT]"
the address of the hostname is the target where the request will be sent to
(outgoing proxy). Use this if the destination host is different then the host
part of the request uri. The hostname is resolved via DNS SRV if supported
(see description for SRV resolving) and no port is given.
.IP "-P, --processes NUMBER"
Start
.BR NUMBER
of processes in parallel to do the send and reply checking. Makes only sence
if a higher number for
.BR -e
is given in the usrloc, message or invite mode.
.IP "-q, --search REGEXP"
match replies against
.BR REGEXP
and return false if no match
occured. Useful for example to detect server name in Server header field.
.IP "-r, --remote-port PORT"
Instead of the default sip port 5060 the
.BR PORT
will be used. Alternatively the remote port can be given within the sip uri of
the
.BR -s
parameter.
.IP "-R, --random-mode"
This activates the randtrash mode. In this mode OPTIONS requests will be send
to server with increasing numbers of randomly crashed characters within this
request. The position within the request and the replacing character are
randomly chosen. Any other response than Bad request (4xx) will stop this
mode. Also three unresponded sends will stop this mode. With the
.BR -t
parameter the maximum of trashed characters can be given.
.IP "-s, --sip-uri SIPURI"
This mandatory option sets the destination of the request. It depends on the
mode if only the server name or also an user name is mandatory. Example for a
full
.BR SIPURI
:
.I sip:test@foo.bar:123
See the note in the description part about SRV lookups for details how the
hostname of this URI is converted into an IP and port.
.IP "-S, --symmetric"
With this option
.B sipsak
will use only one port for sending and receiving messages. With this option
the local port for sending will be the value from the
.BR -l
option. In the default mode
.B sipsak
sends from a random port and listens on the given port from the
.BR -l
option.
.B Note:
With this option
.B sipsak
will not be able to receive replies from servers with asymmetric signaling
(and broken rport implementation) like the Cisco proxy. If you run
.B sipsak
as root and with raw socket support (check the output from the
.BR -V
option) then this option is not required because in this case
.B sipsak
already uses only one port for sending and receiving messages.
.IP "-t, --trash-chars NUMBER"
This parameter specifies the maximum of trashed characters in the randtrash
mode. If omitted
.BR NUMBER
will be set to the length of the request.
.IP "-T, --traceroute-mode"
This activates the traceroute mode. This mode works like the well known
.BR traceroute(8)
command expect that not the number of network hops are counted rather
the number of server on the way to the destination user. Also the round trip
time of each request is printed out, but due to a limitation within the
sip protocol the identity (IP or name) can only determined and printed
out if the response from the server contains a warning header field. In this
mode on each outgoing request the value of the Max-Forwards header field is
increased, starting with one. The maximum of the Max-Forwards header will 255
if no other value is given by the
.BR -m
parameter. Any other response than 483 or 1xx are treated as a final response
and will terminate this mode.
.IP "-u, --auth-username STRING"
Use the given
.BR STRING
as username value for the authentication (different account and
authentication username).
.IP "-U, --usrloc-mode"
This activates the usrloc mode. Without the
.BR -I
or the
.BR -M
option, this only registers users at a registrar. With one of the above
options the previous registered user will also be probed ether with a
simulated call flow (invite, 200, ack) or with an instant message
(message, 200). One password for all users accounts within the usrloc test
can be given with the
.BR -a
option. An user name is mandatory for this mode in the
.BR -s
parameter. The number starting from the
.BR -b
parameter to the
.BR -e
parameter is appended the user name. If the
.BR -b
and the
.BR -e
parameter are omitted, only one runs with the given username, but without
append number to the usernames is done.
.IP "-v, --verbose"
This parameter increases the output verbosity. No
.BR -v
means nearly no output except in traceroute and error messages. The maximum
of three v's prints out the content of all packets received and sent.
.IP "-V, --version"
Prints out the name and version number of
.B sipsak
and the options which were compiled into the binary.
.IP "-w, --extract-ip"
Activates the extraction of the IP or hostname from the Warning header field.
.IP "-W, --nagios-warn NUMBER"
Return Nagios warn exit code (1) if the number of retransmissions before
success was above the given number.
.IP "-x, --expires NUMBER"
Sets the value of the Expires header to the given number.
.IP "-z, --remove-bindings"
Activates the randomly removing of old bindings in the usrloc mode. How many
per cent of the bindings will be removed, is determined by the
USRLOC_REMOVE_PERCENT define within the code (set it before compilation).
Multiple removing of bindings is possible, and cannot be prevented.
.SH RETURN VALUES
The return value 0 means that a 200 was received. 1 means something else
then 1xx or 2xx was received.
2 will be returned on local errors like non resolvable names or
wrong options combination. 3 will be returned on remote errors like socket
errors (e.g. icmp error), redirects without a contact header or simply
no answer (timeout).
If the
.BR -N
option was given the return code will be 2 in case of any (local or remote)
error. 1 in case there have been retransmissions from
.B sipsak
to the server. And 0 if there was no error at all.
.SH CAUTION
Use
.B sipsak
responsibly. Running it in any of the stress modes puts
substantial burden on network and server under test.
.SH EXAMPLES
.IP "sipsak -vv -s sip:nobody@foo.bar"
displays received replies.
.IP "sipsak -T -s sip:nobody@foo.bar"
traces SIP path to nobody.
.IP "sipsak -U -C sip:me@home -x 3600 -a password -s sip:myself@company"
inserts forwarding from work to home for one hour.
.IP "sipsak -f bye.sip -g '!FTAG!345.af23!TTAG!1208.12!' -s sip:myproxy"
reads the file bye.sip, replaces $FTAG$ with 345.af23 and $TTAG$ with
1208.12 and finally send this message to myproxy
.SH LIMITATIONS / NOT IMPLEMENTED
Many servers may decide NOT to include SIP "Warning" header fields.
Unfortunately, this makes displaying IP addresses of SIP servers
in traceroute mode impossible.
IPv6 is not supported.
Missing support for the Record-Route and Route header.
.SH BUGS
sipsak is only tested against the SIP Express Router (ser) though their could
be various bugs. Please feel free to mail them to the author.
.SH AUTHOR
Nils Ohlmeier <nils at sipsak dot org>
.SH "SEE ALSO"
.BR traceroute (8)

@ -0,0 +1,939 @@
/*
* $Id: sipsak.c 397 2006-01-28 21:11:50Z calrissian $
*
* Copyright (C) 2002-2004 Fhg Fokus
* Copyright (C) 2004-2005 Nils Ohlmeier
*
* This file belongs to sipsak, a free sip testing tool.
*
* sipsak 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.
*
* sipsak 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.
*/
/* sipsak written by nils ohlmeier (ohlmeier@fokus.fraunhofer.de).
based up on a modifyed version of shoot.
return codes are now: 0 for an received 200, 1 for all other
received responses, 2 for local errors, and 3 for remote errors.
*/
/* changes by jiri@iptel.org; now messages can be really received;
status code returned is 2 for some local errors , 0 for success
and 1 for remote error -- ICMP/timeout; can be used to test if
a server is alive; 1xx messages are now ignored; windows support
dropped
*/
#include "sipsak.h"
#ifdef HAVE_UNISTD_H
# ifdef HAVE_SYS_TYPES_H
# include <sys/types.h>
# endif
# include <unistd.h>
#endif
#ifdef TIME_WITH_SYS_TIME
# include <sys/time.h>
# include <time.h>
#else
# ifdef HAVE_SYS_TIME_H
# include <sys/time.h>
# else
# include <time.h>
# endif
#endif
#ifdef HAVE_SYS_WAIT_H
# include <sys/wait.h>
#endif
#ifdef HAVE_GETOPT_H
# include <getopt.h>
#endif
#include "helper.h"
#include "header_f.h"
#include "shoot.h"
#include "exit_code.h"
static void sigchld_handler(int signo)
{
int chld_status;
pid_t chld;
while ((chld = waitpid(-1, &chld_status, WNOHANG)) > 0);
}
void print_version() {
printf("%s %s by Nils Ohlmeier\n", PACKAGE_NAME, PACKAGE_VERSION);
printf(" Copyright (C) 2002-2004 FhG Fokus\n");
printf(" Copyright (C) 2004-2005 Nils Ohlmeier\n");
printf(" report bugs to %s\n\n", PACKAGE_BUGREPORT);
printf(
" shoot : sipsak [-f FILE] [-L] -s SIPURI\n"
" trace : sipsak -T -s SIPURI\n"
" usrloc : sipsak -U [-I|M] [-b NUMBER] [-e NUMBER] [-x NUMBER] [-z NUMBER] -s SIPURI\n"
" usrloc : sipsak -I|M [-b NUMBER] [-e NUMBER] -s SIPURI\n"
" usrloc : sipsak -U [-C SIPURI] [-x NUMBER] -s SIPURI\n"
" message: sipsak -M [-B STRING] [-O STRING] [-c SIPURI] -s SIPURI\n"
" flood : sipsak -F [-e NUMBER] -s SIPURI\n"
" random : sipsak -R [-t NUMBER] -s SIPURI\n\n"
" additional parameter in every mode:\n"
);
printf(" [-a PASSWORD] [-d] [-i] [-H HOSTNAME] [-l PORT] [-m NUMBER] [-n] "
"[-N]\n"
" [-r PORT] [-v] [-V] [-w]\n\n"
);
}
void print_long_help() {
print_version();
printf(
" --help displays this help message\n"
" --version prints version string only\n"
" --filename=FILE the file which contains the SIP message to send\n"
" use - for standard input\n"
" --no-crlf de-activate CR (\\r) insertion\n"
" --sip-uri=SIPURI the destination server uri in form\n"
" sip:[user@]servername[:port]\n"
" --traceroute activates the traceroute mode\n"
);
printf(" --usrloc-mode activates the usrloc mode\n"
" --invite-mode simulates a successful calls with itself\n"
" --message-mode sends messages to itself\n"
" --contact=SIPURI use the given uri as Contact in REGISTER\n"
" --appendix-begin=NUMBER the starting number appendix to the user name (default: 0)\n"
" --appendix-end=NUMBER the ending numer of the appendix to the user name\n"
" --sleep=NUMBER sleep number ms before sending next request\n"
);
printf(" --expires=NUMBER the expires header field value (default: 15)\n"
" --remove-bindings=NUMBER activates randomly removing of user bindings\n"
" --flood-mode activates the flood mode\n"
" --random-mode activates the random modues (dangerous)\n"
" --trash-chars=NUMBER the maximum number of trashed character in random mode\n"
" (default: request length)\n"
);
printf(" --local-port=PORT the local port to use (default: any)\n"
" --remote-port=PORT the remote port to use (default: 5060)\n"
" --outbound-proxy=HOSTNAME request target (outbound proxy)\n"
" --hostname=HOSTNAME overwrites the local hostname in all headers\n"
" --max-forwards=NUMBER the value for the max-forwards header field\n"
" --numeric use FQDN instead of IPs in the Via-Line\n");
printf(" --processes=NUMBER Divide the workflow among the number of processes\n"
" --auth-username=STRING username for authentication\n"
);
printf(" --no-via deactivate the insertion of a Via-Line\n"
" --password=PASSWORD password for authentication\n"
" (if omitted password=username)\n"
" --ignore-redirects ignore redirects\n"
" --verbose each v produces more verbosity (max. 3)\n"
" --extract-ip extract IP from the warning in reply\n"
" --replace-string=STRING replacement for a special mark in the message\n"
" --replace activates replacement of variables\n"
);
printf(" --nagios-code returns exit codes Nagios compliant\n"
" --nagios-warn=NUMBER return Nagios warning if retrans > number\n"
" --message-body=STRING send a message with string as body\n"
" --disposition=STRING Content-Disposition value\n"
" --search=REGEXP search for a RegExp in replies and return error\n"
" on failfure\n"
" --timing=NUMBER number of test runs and print just the timings\n"
" --symmetric send and received on the same port\n"
" --from=SIPURI use the given uri as From in MESSAGE\n"
" --timeout-factor=NUMBER timeout multiplier for INVITE transactions\n"
" and reliable transports (default: 64)\n"
" --transport=STRING specify transport to be used\n"
" --headers=STRING adds additional headers to the request\n"
);
exit_code(0);
}
/* prints out some usage help and exits */
void print_help() {
print_version();
printf(
" -h displays this help message\n"
" -V prints version string only\n"
" -f FILE the file which contains the SIP message to send\n"
" use - for standard input\n"
" -L de-activate CR (\\r) insertion in files\n"
" -s SIPURI the destination server uri in form\n"
" sip:[user@]servername[:port]\n"
" -T activates the traceroute mode\n"
" -U activates the usrloc mode\n"
" -I simulates a successful calls with itself\n"
" -M sends messages to itself\n"
);
printf(
" -C SIPURI use the given uri as Contact in REGISTER\n"
" -b NUMBER the starting number appendix to the user name (default: 0)\n"
" -e NUMBER the ending numer of the appendix to the user name\n"
" -o NUMBER sleep number ms before sending next request\n"
" -x NUMBER the expires header field value (default: 15)\n"
" -z NUMBER activates randomly removing of user bindings\n"
" -F activates the flood mode\n"
);
printf(
" -R activates the random modues (dangerous)\n"
" -t NUMBER the maximum number of trashed character in random mode\n"
" (default: request length)\n"
" -l PORT the local port to use (default: any)\n"
" -r PORT the remote port to use (default: 5060)\n"
" -p HOSTNAME request target (outbound proxy)\n"
);
printf(
" -H HOSTNAME overwrites the local hostname in all headers\n"
" -m NUMBER the value for the max-forwards header field\n"
" -n use FQDN instead of IPs in the Via-Line\n"
" -i deactivate the insertion of a Via-Line\n"
" -a PASSWORD password for authentication\n"
" (if omitted password=\"\")\n"
" -u STRING Authentication username\n"
);
printf(
" -d ignore redirects\n"
" -v each v produces more verbosity (max. 3)\n"
" -w extract IP from the warning in reply\n"
" -g STRING replacement for a special mark in the message\n"
" -G activates replacement of variables\n"
" -N returns exit codes Nagios compliant\n"
" -q STRING search for a RegExp in replies and return error\n"
" on failure\n");
printf(" -W NUMBER return Nagios warning if retrans > number\n"
" -B STRING send a message with string as body\n"
" -O STRING Content-Disposition value\n"
" -P NUMBER Number of processes to start\n"
" -A NUMBER number of test runs and print just timings\n"
" -S use same port for receiving and sending\n"
" -c SIPURI use the given uri as From in MESSAGE\n"
" -D NUMBER timeout multiplier for INVITE transactions\n"
" and reliable transports (default: 64)\n"
" -E STRING specify transport to be used\n"
" -j STRING adds additional headers to the request\n"
);
exit_code(0);
}
int main(int argc, char *argv[])
{
FILE *pf;
char buff[BUFSIZE];
int c, i, port;
unsigned int tsp;
char *scheme, *user, *host, *backup;
pid_t pid;
struct timespec ts;
int upp;
#ifdef HAVE_GETOPT_LONG
int option_index = 0;
static struct option l_opts[] = {
{"help", 0, 0, 'X'},
{"version", 0, 0, 'V'},
{"filename", 1, 0, 'f'},
{"sip-uri", 1, 0, 's'},
{"traceroute-mode", 0, 0, 'T'},
{"usrloc-mode", 0, 0, 'U'},
{"invite-mode", 0, 0, 'I'},
{"message-mode", 0, 0, 'M'},
{"contact", 1, 0, 'C'},
{"appendix-begin", 1, 0, 'b'},
{"appendix-end", 1, 0, 'e'},
{"sleep", 1, 0, 'o'},
{"expires", 1, 0, 'x'},
{"remove-bindings", 1, 0, 'z'},
{"flood-mode", 0, 0, 'F'},
{"random-mode", 0, 0, 'R'},
{"trash-chars", 1, 0, 't'},
{"local-port", 1, 0, 'l'},
{"remote-port", 1, 0, 'r'},
{"outbound-proxy", 1, 0, 'p'},
{"hostname", 1, 0, 'H'},
{"max-fowards", 1, 0, 'm'},
{"numeric", 0, 0, 'n'},
{"no-via", 0, 0, 'i'},
{"password", 1, 0, 'a'},
{"ignore-redirects", 0, 0, 'd'},
{"verbose", 0, 0, 'v'},
{"extract-ip", 0, 0, 'w'},
{"replace-string", 0, 0, 'g'},
{"replace", 0, 0, 'G'},
{"nagios-code", 0, 0, 'N'},
{"nagios-warn", 1, 0, 'W'},
{"search", 1, 0, 'q'},
{"message-body", 1, 0, 'B'},
{"disposition", 1, 0, 'O'},
{"processes", 1, 0, 'P'},
{"auth-username", 1, 0, 'u'},
{"no-crlf", 0, 0, 'L'},
{"timing", 1, 0, 'A'},
{"symmetric", 0, 0, 'S'},
{"from", 1, 0, 'c'},
{"timeout-factor", 1, 0, 'D'},
{"transport", 1, 0, 'E'},
{"headers", 1, 0, 'j'},
{0, 0, 0, 0}
};
#endif
/* some initialisation to be shure */
file_b=uri_b=trace=lport=usrloc=flood=verbose=randtrash=trashchar = 0;
warning_ext=rand_rem=nonce_count=replace_b=invite=message = 0;
sleep_ms=empty_contact=nagios_warn=timing=outbound_proxy=symmetric = 0;
namebeg=nameend=maxforw= -1;
numeric=via_ins=redirects=fix_crlf=processes = 1;
username=password=replace_str=hostname=contact_uri=mes_body = NULL;
con_dis=auth_username=from_uri=headers = NULL;
scheme = user = host = backup = req = rep = rec = NULL;
re = NULL;
address= 0;
transport=tsp = 0;
rport = port = 0;
expires_t = USRLOC_EXP_DEF;
inv_final = 64 * SIP_T1;
memset(buff, 0, BUFSIZE);
memset(fqdn, 0, FQDN_SIZE);
if (argc==1) {
print_help();
}
/* lots of command line switches to handle*/
#ifdef HAVE_GETOPT_LONG
while ((c=getopt_long(argc, argv, "a:A:b:B:c:C:dD:e:E:f:Fg:GhH:iIj:l:Lm:MnNo:O:p:P:q:r:Rs:St:Tu:UvVwW:x:Xz:", l_opts, &option_index)) != EOF){
#else
while ((c=getopt(argc, argv, "a:A:b:B:c:C:dD:e:E:f:Fg:GhH:iIj:l:Lm:MnNo:O:p:P:q:r:Rs:St:Tu:UvVwW:x:z:")) != EOF){
#endif
switch(c){
case 'a':
if (strlen(optarg) == 1 && STRNCASECMP(optarg, "-", 1) == 0) {
password = str_alloc(SIPSAK_MAX_PASSWD_LEN);
printf("Please enter the password (max. length %i): ", SIPSAK_MAX_PASSWD_LEN);
if (read_stdin(password, SIPSAK_MAX_PASSWD_LEN, 1) == 0) {
exit_code(0);
}
}
else {
password=str_alloc(strlen(optarg) + 1);
strncpy(password, optarg, strlen(optarg));
}
break;
case 'A':
timing=str_to_int(optarg);
break;
case 'b':
namebeg=str_to_int(optarg);
break;
case 'B':
mes_body=str_alloc(strlen(optarg) + 1);
strncpy(mes_body, optarg, strlen(optarg));
break;
case 'c':
backup=str_alloc(strlen(optarg)+1);
strncpy(backup, optarg, strlen(optarg));
parse_uri(backup, &scheme, &user, &host, &port);
if (scheme == NULL) {
fprintf(stderr, "error: missing scheme in From URI\n");
exit_code(2);
}
else if (user == NULL) {
fprintf(stderr, "error: missing username in From URI\n");
exit_code(2);
}
else if (host == NULL) {
fprintf(stderr, "error: missing host in From URI\n");
exit_code(2);
}
else {
from_uri=str_alloc(strlen(optarg)+1);
strncpy(from_uri, optarg, strlen(optarg));
}
free(backup);
break;
case 'C':
if ((strlen(optarg) == 5 && STRNCASECMP(optarg, "empty", 5) == 0) ||
(strlen(optarg) == 4 && STRNCASECMP(optarg, "none", 4) == 0)) {
empty_contact = 1;
}
else if (strlen(optarg) == 1 && STRNCASECMP(optarg, "*", 1) == 0) {
contact_uri=str_alloc(strlen(optarg)+1);
strncpy(contact_uri, optarg, strlen(optarg));
}
else {
backup=str_alloc(strlen(optarg)+1);
strncpy(backup, optarg, strlen(optarg));
parse_uri(backup, &scheme, &user, &host, &port);
if (scheme == NULL) {
fprintf(stderr, "error: REGISTER Contact uri doesn't not contain "
"sip:, sips:, *, or is not empty\n");
exit_code(2);
}
else if (user == NULL) {
fprintf(stderr, "error: missing username in Contact uri\n");
exit_code(2);
}
else if (host == NULL) {
fprintf(stderr, "error: missing host in Contact uri\n");
exit_code(2);
}
else {
contact_uri=str_alloc(strlen(optarg)+1);
strncpy(contact_uri, optarg, strlen(optarg));
}
free(backup);
}
break;
case 'd':
redirects=0;
break;
case 'D':
inv_final = str_to_int(optarg) * SIP_T1;
break;
case 'e':
nameend=str_to_int(optarg);
break;
case 'E':
if (strlen(optarg) == 3 &&
STRNCASECMP(optarg, "udp", 3) == 0) {
transport = SIP_UDP_TRANSPORT;
}
else if (strlen(optarg) == 3 &&
STRNCASECMP(optarg, "tcp", 3) == 0) {
transport = SIP_TCP_TRANSPORT;
}
else if (strlen(optarg) == 3 &&
STRNCASECMP(optarg, "tls", 3) == 0) {
fprintf(stderr, "error: TLS is not supported yet, supported values: udp, tcp\n");
exit_code(2);
transport = SIP_TLS_TRANSPORT;
}
else {
fprintf(stderr, "error: unsupported transport '%s', supported values: udp, tcp\n", optarg);
exit_code(2);
}
break;
case 'F':
flood=1;
break;
case 'f':
if (strlen(optarg) != 1 && STRNCASECMP(optarg, "-", 1) != 0) {
/* file is opened in binary mode so that the cr-lf is
preserved */
pf = fopen(optarg, "rb");
if (!pf){
fprintf(stderr, "error: unable to open the file '%s'.\n", optarg);
exit_code(2);
}
if (fread(buff, 1, sizeof(buff), pf) >= sizeof(buff)){
fprintf(stderr, "error:the file is too big. try files of less "
"than %i bytes.\n", BUFSIZE);
fprintf(stderr, " or recompile the program with bigger "
"BUFSIZE defined.\n");
exit_code(2);
}
fclose(pf);
}
else if (strlen(optarg) == 1 && STRNCASECMP(optarg, "-", 1) == 0) {
if (read_stdin(&buff[0], sizeof(buff), 0) == 0) {
exit_code(0);
}
}
else {
fprintf(stderr, "error: unable to handle input file name: %s\n", optarg);
exit_code(2);
}
file_b=1;
break;
case 'g':
replace_str=optarg;
break;
case 'G':
replace_b=1;
break;
case 'h':
print_help();
break;
case 'H':
hostname=optarg;
break;
case 'i':
via_ins=0;
break;
case 'I':
invite=1;
break;
case 'j':
headers=optarg;
break;
case 'l':
lport=str_to_int(optarg);
break;
case 'L':
fix_crlf=0;
break;
case 'm':
maxforw=str_to_int(optarg);
break;
case 'M':
message=1;
break;
case 'n':
numeric = 0;
break;
case 'N':
exit_mode=EM_NAGIOS;
break;
case 'o':
sleep_ms = 0;
if (strlen(optarg) == 4 && STRNCASECMP(optarg, "rand", 4) == 0) {
sleep_ms = -2;
}
else {
sleep_ms = str_to_int(optarg);
}
break;
case 'O':
con_dis=str_alloc(strlen(optarg) + 1);
strncpy(con_dis, optarg, strlen(optarg));
break;
case 'p':
parse_uri(optarg, &scheme, &user, &host, &rport);
if (host == NULL) {
fprintf(stderr, "error: missing in host in outbound proxy\n");
exit_code(2);
}
if (is_ip(host)) {
address = getaddress(host);
if (transport == 0)
transport = SIP_UDP_TRANSPORT;
}
else {
if (!rport) {
address = getsrvadr(host, &rport, &tsp);
if (tsp != 0)
transport = tsp;
}
if (!address) {
address = getaddress(host);
if (address && verbose > 1)
printf("using A record: %s\n", host);
}
if (!address){
fprintf(stderr, "error:unable to determine the outbound proxy "
"address\n");
exit_code(2);
}
}
outbound_proxy=1;
break;
case 'P':
processes=str_to_int(optarg);
break;
case 'q':
if (re) {
/* previously allocated -- free */
regfree(re);
} else {
/* never tried -- allocate */
re=malloc(sizeof(regex_t));
};
if (!re) {
fprintf(stderr, "Error: can't allocate RE\n");
exit_code(2);
};
if (regcomp(re, optarg, REG_EXTENDED|REG_ICASE|REG_NEWLINE )!=0) {
fprintf(stderr, "Error: compiling RE: %s\n", optarg );
exit_code(2);
};
break;
case 'r':
port = 0;
port=str_to_int(optarg);
if (rport) {
fprintf(stderr, "warning: you are overwritting the destination port with the r argument\n");
}
rport = port;
break;
case 'R':
randtrash=1;
break;
case 's':
parse_uri(optarg, &scheme, &user, &host, &port);
if (scheme == NULL) {
fprintf(stderr, "error: missing scheme in sip uri\n");
exit_code(2);
}
if (strlen(optarg) == 4 && STRNCASECMP(optarg,"sips",4) == 0){
fprintf(stderr, "error: sips is not supported yet\n");
exit_code(2);
}
else if (strlen(optarg) != 3 || STRNCASECMP(optarg,"sip",3) != 0){
fprintf(stderr, "error: scheme of sip uri has to be sip\n");
exit_code(2);
}
if (user != NULL) {
username = user;
}
if (host != NULL) {
domainname = host;
}
else {
fprintf(stderr, "error: missing hostname in sip uri\n");
exit_code(2);
}
if (port && !rport) {
rport = port;
}
if (is_ip(domainname)) {
address = getaddress(domainname);
if (transport == 0)
transport = SIP_UDP_TRANSPORT;
}
else {
if (!rport && !address) {
address = getsrvadr(domainname, &rport, &tsp);
if (tsp != 0)
transport = tsp;
}
if (!address) {
address = getaddress(domainname);
if (address && verbose > 1)
printf("using A record: %s\n", domainname);
}
if (!address){
fprintf(stderr, "error:unable to determine the IP address for: %s\n", domainname);
exit_code(2);
}
}
if (port != 0) {
backup = str_alloc(strlen(domainname)+1+6);
snprintf(backup, strlen(domainname)+6, "%s:%i", domainname, port);
domainname = backup;
}
uri_b=1;
break;
case 'S':
fprintf(stderr, "warning: symmetric does not work with a-symmetric servers\n");
symmetric=1;
break;
case 't':
trashchar=str_to_int(optarg);
break;
case 'T':
trace=1;
break;
case 'U':
usrloc=1;
break;
case 'u':
auth_username=str_alloc(strlen(optarg) + 1);
strncpy(auth_username, optarg, strlen(optarg));
break;
case 'v':
verbose++;
break;
case 'V':
printf("sipsak %s by Nils Ohlmeier\n Copyright (C) 2002-2004"
" FhG Fokus\n Copyright (C) 2004-2005 Nils Ohlmeier\n",
SIPSAK_VERSION);
printf(" compiled with DEFAULT_TIMEOUT=%i, FQDN_SIZE=%i",
DEFAULT_TIMEOUT, FQDN_SIZE);
#ifdef RAW_SUPPORT
printf(", RAW_SUPPORT");
#endif
#ifdef HAVE_GETOPT_LONG
printf(", LONG_OPTS");
#endif
#ifdef HAVE_GNUTLS
printf(", GNUTLS_MD5");
#else
# ifdef HAVE_FULL_OPENSSL
printf(", OPENSSL_MD5");
# else
printf(", INTERNAL_MD5");
# endif
#endif
#ifdef HAVE_OPENSSL_SHA1
printf(", OPENSSL_SHA1");
#endif
#ifdef HAVE_CARES_H
printf(", SRV_SUPPORT(ARES)");
#else
# ifdef HAVE_RULI_H
printf(", SRV_SUPPORT(RULI)");
# endif
#endif
#ifdef HAVE_STRCASESTR
printf(", STR_CASE_INSENSITIVE");
#endif
#ifdef HAVE_STRNCASECMP
printf(", CMP_CASE_INSENSITIVE");
#endif
printf("\n");
exit_code(0);
break;
case 'w':
warning_ext=1;
break;
case 'W':
nagios_warn = str_to_int(optarg);
break;
case 'x':
expires_t=str_to_int(optarg);
break;
#ifdef HAVE_GETOPT_LONG
case 'X':
print_long_help();
break;
#endif
case 'z':
rand_rem=str_to_int(optarg);
if (rand_rem < 0 || rand_rem > 100) {
fprintf(stderr, "error: z option must between 0 and 100\n");
exit_code(2);
}
break;
default:
fprintf(stderr, "error: unknown parameter %c\n", c);
exit_code(2);
break;
}
}
if (rport == 0) {
rport = 5060;
}
if (rport > 65535 || rport <= 0) {
fprintf(stderr, "error: invalid remote port: %i\n", rport);
exit_code(2);
}
if (transport == 0) {
transport = SIP_UDP_TRANSPORT;
}
/* replace LF with CRLF if we read from a file */
if ((file_b) && (fix_crlf)) {
insert_cr(buff);
}
if (headers) {
backup = str_alloc(strlen(headers) + 30); // FIXME
strcpy(backup, headers);
headers = backup;
replace_string(headers, "\\n", "\r\n");
backup = headers + strlen(headers) - 1;
if (*backup != '\n') {
strcpy(backup + 1, "\r\n");
}
if (file_b)
insert_header(buff, headers, 1);
}
/* lots of conditions to check */
if (trace) {
if (usrloc || flood || randtrash) {
fprintf(stderr, "error: trace can't be combined with usrloc, random or "
"flood\n");
exit_code(2);
}
if (!uri_b) {
fprintf(stderr, "error: for trace mode a SIPURI is realy needed\n");
exit_code(2);
}
if (file_b) {
fprintf(stderr, "warning: file will be ignored for tracing.");
}
if (!username) {
fprintf(stderr, "error: for trace mode without a file the SIPURI have to "
"contain a username\n");
exit_code(2);
}
if (!via_ins){
fprintf(stderr, "warning: Via-Line is needed for tracing. Ignoring -i\n");
via_ins=1;
}
if (!warning_ext) {
fprintf(stderr, "warning: IP extract from warning activated to be more "
"informational\n");
warning_ext=1;
}
if (maxforw==-1) maxforw=255;
}
else if (usrloc || invite || message) {
if (trace || flood || randtrash) {
fprintf(stderr, "error: usrloc can't be combined with trace, random or "
"flood\n");
exit_code(2);
}
if (!username || !uri_b) {
fprintf(stderr, "error: for the USRLOC mode you have to give a SIPURI with "
"a username\n at least\n");
exit_code(2);
}
if (namebeg>0 && nameend==-1) {
fprintf(stderr, "error: if a starting numbers is given also an ending "
"number have to be specified\n");
exit_code(2);
}
if (invite && message) {
fprintf(stderr, "error: invite and message tests are XOR\n");
exit_code(2);
}
if (!usrloc && invite && !lport) {
fprintf(stderr, "warning: Do NOT use the usrloc invite mode without "
"registering sipsak before.\n See man page for "
"details.\n");
exit_code(2);
}
if (contact_uri!=NULL) {
if (invite || message) {
fprintf(stderr, "error: Contact uri is not support for invites or "
"messages\n");
exit_code(2);
}
if (nameend!=-1 || namebeg!=-1) {
fprintf(stderr, "warning: ignoring starting or ending number if Contact"
" is given\n");
nameend=namebeg=0;
}
if (rand_rem) {
fprintf(stderr, "warning: ignoring -z option when Contact is given\n");
rand_rem=0;
}
}
if (via_ins) {
fprintf(stderr, "warning: ignoring -i option when in usrloc mode\n");
via_ins=0;
}
if (nameend==-1)
nameend=0;
if (namebeg==-1)
namebeg=0;
}
else if (flood) {
if (trace || usrloc || randtrash) {
fprintf(stderr, "error: flood can't be combined with trace, random or "
"usrloc\n");
exit_code(2);
}
if (!uri_b) {
fprintf(stderr, "error: we need at least a sip uri for flood\n");
exit_code(2);
}
if (redirects) {
fprintf(stderr, "warning: redirects are not expected in flood. "
"disableing\n");
redirects=0;
}
}
else if (randtrash) {
if (trace || usrloc || flood) {
fprintf(stderr, "error: random can't be combined with trace, flood or "
"usrloc\n");
exit_code(2);
}
if (!uri_b) {
fprintf(stderr, "error: need at least a sip uri for random\n");
exit_code(2);
}
if (redirects) {
fprintf(stderr, "warning: redirects are not expected in random. "
"disableing\n");
redirects=0;
}
if (verbose) {
fprintf(stderr, "warning: random characters may destroy your terminal "
"output\n");
}
}
else if (mes_body) {
if (!message) {
fprintf(stderr, "warning: to send a message mode (-M) is required. activating\n");
message=1;
}
if (!uri_b) {
fprintf(stderr, "error: need at least a sip uri to send a meesage\n");
exit_code(2);
}
if (nameend==-1)
nameend=0;
if (namebeg==-1)
namebeg=0;
}
else {
if (!uri_b) {
fprintf(stderr, "error: a spi uri is needed at least\n");
exit_code(2);
}
}
switch (transport) {
case SIP_TLS_TRANSPORT:
transport_str = TRANSPORT_TLS_STR;
break;
case SIP_TCP_TRANSPORT:
transport_str = TRANSPORT_TCP_STR;
break;
case SIP_UDP_TRANSPORT:
transport_str = TRANSPORT_UDP_STR;
break;
default:
fprintf(stderr, "unknown transport: %i\n", transport);
exit_code(2);
}
/* determine our hostname */
get_fqdn();
/* this is not a cryptographic random number generator,
but hey this is only a test-tool => should be satisfying*/
srand(time(0) ^ getpid());
if (processes > 1) {
if (signal(SIGCHLD , sigchld_handler) == SIG_ERR ) {
fprintf(stderr, "error: Could not install SIGCHLD handler\n");
exit_code(2);
}
}
for(i = 0; i < processes - 1; i++) {
if ((pid = fork()) < 0) {
fprintf(stderr, "error: Cannot fork\n");
exit_code(2);
}
if (pid == 0){
/* child */
upp = (nameend - namebeg + 1) / processes;
namebeg = namebeg + upp * i;
nameend = namebeg + upp;
shoot(&buff[0], sizeof(buff));
} else {
if (lport) {
lport++;
}
}
/* Delay execution of children so that the
* time of the first transmission gets spread over
* the retransmission interval evenly
*/
ts.tv_sec = 0;
ts.tv_nsec = (float)DEFAULT_TIMEOUT / (float)processes * (float)1000 * (float)1000;
nanosleep(&ts, 0);
}
/* here we go...*/
if (processes > 1) {
upp = (nameend - namebeg + 1) / processes;
namebeg = namebeg + upp * i;
nameend = namebeg + upp;
}
shoot(&buff[0], sizeof(buff));
/* normaly we won't come back here, but to satisfy the compiler */
return 0;
}

@ -0,0 +1,312 @@
/*
* $Id: sipsak.h 397 2006-01-28 21:11:50Z calrissian $
*
* Copyright (C) 2002-2004 Fhg Fokus
* Copyright (C) 2004-2005 Nils Ohlmeier
*
* This file belongs to sipsak, a free sip testing tool.
*
* sipsak 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.
*
* sipsak 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.
*/
#ifndef SIPSAK_H
#define SIPSAK_H
#if HAVE_CONFIG_H
# include "config.h"
#endif
#ifdef HAVE_STDIO_H
# include <stdio.h>
#endif
#ifdef HAVE_STDLIB_H
# include <stdlib.h>
#endif
#ifdef HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif
#ifdef HAVE_REGEX_H
# include <regex.h>
#endif
#ifdef HAVE_SYS_PARAM_H
# include <sys/param.h>
#endif
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif
#ifndef INET_ADDRSTRLEN
# define INET_ADDRSTRLEN 16
#endif
#ifdef HAVE_SIGNAL_H
# include <signal.h>
#endif
#ifdef HAVE_LIMITS_H
# include <limits.h>
#endif
#ifndef INT_MAX
# define INT_MAX 2147483648
#endif
#ifdef HAVE_STRCASESTR
# define __USE_GNU
# define STRCASESTR(s1,s2) strcasestr(s1,s2)
#else
# define STRCASESTR(s1,s2) strstr(s1,s2)
#endif
#ifdef HAVE_STRNCASECMP
# define STRNCASECMP(s1,s2,s3) strncasecmp(s1,s2,s3)
#else
# define STRNCASECMP(s1,s2,s3) strncmp(s1,s2,s3)
#endif
#ifdef HAVE_STRING_H
# include <string.h>
#endif
#ifdef HAVE_GNUTLS
# define HAVE_EXTERNAL_MD5
#else
# ifdef HAVE_OPENSSL_MD5_H
# ifdef HAVE_CRYPTO_WITH_MD5
# define HAVE_FULL_OPENSSL
# define HAVE_EXTERNAL_MD5
# endif
# endif
#endif
#ifdef HAVE_OPENSSL_SHA_H
# ifdef HAVE_CRYPTO_WITH_SHA1
# define HAVE_OPENSSL_SHA1
# endif
#endif
#ifndef REG_NOERROR
# define REG_NOERROR 0
#endif
#ifdef HAVE_SYS_PARAM_H
# ifdef MAXHOSTNAMELEN
# define FQDN_SIZE MAXHOSTNAMELEN + 1
# else
# define FQDN_SIZE 100
# endif
#else
# define FQDN_SIZE 100
#endif
#ifdef HAVE_CONFIG_H
# define SIP_T1 DEFAULT_TIMEOUT
#else
# define SIP_T1 500
#endif
#define SIP_T2 8*SIP_T1
#define SIPSAK_VERSION PACKAGE_VERSION
#define BUFSIZE 4096
#define SIPSAK_MAX_PASSWD_LEN 20
#define REQ_REG 1
#define REQ_REM 2
#define REQ_INV 3
#define REQ_MES 4
#define REQ_OPT 5
#define REQ_FLOOD 6
#define REQ_RAND 7
#undef WITH_TLS_TRANSP
#define SIP_TLS_TRANSPORT 1
#define SIP_TCP_TRANSPORT 2
#define SIP_UDP_TRANSPORT 3
#define TRANSPORT_TLS_STR "TLS"
#define TRANSPORT_TCP_STR "TCP"
#define TRANSPORT_UDP_STR "UDP"
#define TRANSPORT_STR_LEN 3
#define VIA_SIP_STR "Via: SIP/2.0/"
#define VIA_SIP_STR_LEN (sizeof(VIA_SIP_STR) - 1)
#define SIP20_STR " SIP/2.0\r\n"
#define SIP20_STR_LEN (sizeof(SIP20_STR) - 1)
#define SIP200_STR "SIP/2.0 200 OK\r\n"
#define SIP200_STR_LEN (sizeof(SIP200_STR) - 1)
#define INV_STR "INVITE"
#define INV_STR_LEN (sizeof(INV_STR) - 1)
#define REG_STR "REGISTER"
#define REG_STR_LEN (sizeof(REG_STR) - 1)
#define OPT_STR "OPTIONS"
#define OPT_STR_LEN (sizeof(OPT_STR) - 1)
#define MES_STR "MESSAGE"
#define MES_STR_LEN (sizeof(MES_STR) - 1)
#define ACK_STR "ACK"
#define ACK_STR_LEN (sizeof(ACK_STR) - 1)
#define FROM_STR "From: "
#define FROM_STR_LEN (sizeof(FROM_STR) - 1)
#define FROM_SHORT_STR "\nf: "
#define FROM_SHORT_STR_LEN (sizeof(FROM_SHORT_STR) - 1)
#define TO_STR "To: "
#define TO_STR_LEN (sizeof(TO_STR) - 1)
#define TO_SHORT_STR "\nt: "
#define TO_SHORT_STR_LEN (sizeof(TO_SHORT_STR) - 1)
#define VIA_STR "Via: "
#define VIA_STR_LEN (sizeof(VIA_STR) - 1)
#define VIA_SHORT_STR "\nv: "
#define VIA_SHORT_STR_LEN (sizeof(VIA_SHORT_STR) - 1)
#define CALL_STR "Call-ID: "
#define CALL_STR_LEN (sizeof(CALL_STR) - 1)
#define CALL_SHORT_STR "\ni: "
#define CALL_SHORT_STR_LEN (sizeof(CALL_SHORT_STR) - 1)
#define MAX_FRW_STR "Max-Forwards: "
#define MAX_FRW_STR_LEN (sizeof(MAX_FRW_STR) - 1)
#define CSEQ_STR "CSeq: "
#define CSEQ_STR_LEN (sizeof(CSEQ_STR) - 1)
#define CONT_STR "Contact: "
#define CONT_STR_LEN (sizeof(CONT_STR) - 1)
#define CONT_SHORT_STR "\nm: "
#define CONT_SHORT_STR_LEN (sizeof(CONT_SHORT_STR) - 1)
#define CON_TYP_STR "Content-Type: "
#define CON_TYP_STR_LEN (sizeof(CON_TYP_STR) - 1)
#define CON_TYP_SHORT_STR "\nc: "
#define CON_TYP_SHORT_STR_LEN (sizeof(CON_TYP_SHORT_STR) - 1)
#define CON_DIS_STR "Content-Disposition: "
#define CON_DIS_STR_LEN (sizeof(CON_DIS_STR) - 1)
#define TXT_PLA_STR "text/plain"
#define TXT_PLA_STR_LEN (sizeof(TXT_PLA_STR) - 1)
#define ACP_STR "Accept: "
#define ACP_STR_LEN (sizeof(ACP_STR) - 1)
#define CON_LEN_STR "Content-Length: "
#define CON_LEN_STR_LEN (sizeof(CON_LEN_STR) - 1)
#define CON_LEN_SHORT_STR "\nl: "
#define CON_LEN_SHORT_STR_LEN (sizeof(CON_LEN_SHORT_STR) - 1)
#define RR_STR "Record-Route: "
#define RR_STR_LEN (sizeof(RR_STR) - 1)
#define ROUTE_STR "Route: "
#define ROUTE_STR_LEN (sizeof(ROUTE_STR) - 1)
#define SIPSAK_MES_STR "test message from SIPsak for user "
#define SIPSAK_MES_STR_LEN (sizeof(SIPSAK_MES_STR) - 1)
#define EXP_STR "Expires: "
#define EXP_STR_LEN (sizeof(EXP_STR) - 1)
#define CON_EXP_STR "expires="
#define CON_EXP_STR_LEN (sizeof(CON_EXP_STR) - 1)
#define WWWAUTH_STR "WWW-Authenticate: "
#define WWWAUTH_STR_LEN (sizeof(WWWAUTH_STR) - 1)
#define PROXYAUTH_STR "Proxy-Authenticate: "
#define PROXYAUTH_STR_LEN (sizeof(PROXYAUTH_STR) - 1)
#define AUTH_STR "Authorization: Digest "
#define AUTH_STR_LEN (sizeof(AUTH_STR) - 1)
#define PROXYAUZ_STR "Proxy-Authorization: Digest "
#define PROXYAUZ_STR_LEN (sizeof(PROXYAUZ_STR) - 1)
#define ALGO_STR "algorithm="
#define ALGO_STR_LEN (sizeof(ALGO_STR) - 1)
#define MD5_STR "MD5, "
#define MD5_STR_LEN (sizeof(MD5_STR) - 1)
#define SHA1_STR "SHA1, "
#define SHA1_STR_LEN (sizeof(SHA1_STR) - 1)
#define REALM_STR "realm="
#define REALM_STR_LEN (sizeof(REALM_STR) - 1)
#define OPAQUE_STR "opaque="
#define OPAQUE_STR_LEN (sizeof(OPAQUEE_STR) - 1)
#define NONCE_STR "nonce="
#define NONCE_STR_LEN (sizeof(NONCE_STR) - 1)
#define RESPONSE_STR "response="
#define RESPONSE_STR_LEN (sizeof(RESPONSE_STR) - 1)
#define QOP_STR "qop="
#define QOP_STR_LEN (sizeof(QOP_STR) - 1)
#define QOPAUTH_STR "auth"
#define QOPAUTH_STR_LEN (sizeof(QOPAUTH_STR) - 1)
#define NC_STR "nc="
#define NC_STR_LEN (sizeof(NC_STR) - 1)
#define EMPTY_STR ""
#define EMPTY_STR_LEN (sizeof(EMPTY_STR) - 1)
#define UA_STR "User-Agent: "
#define UA_STR_LEN (sizeof(UA_STR) - 1)
#define SUB_STR "Subject: "
#define SUB_STR_LEN (sizeof(SUB_STR) - 1)
#define SIP100_STR "SIP/2.0 100"
#define SIP100_STR_LEN (sizeof(SIP100_STR) - 1)
#define TRANSPORT_PARAMETER_STR ";transport="
#define TRANSPORT_PARAMETER_STR_LEN (sizeof(TRANSPORT_PARAMETER_STR) - 1)
#define USRLOC_EXP_DEF 15
#define FLOOD_METH "OPTIONS"
#define SIPSAK_HASHLEN_MD5 16
#define SIPSAK_HASHHEXLEN_MD5 2 * SIPSAK_HASHLEN_MD5
#ifdef HAVE_OPENSSL_SHA1
# define SIPSAK_HASHLEN_SHA1 20
# define SIPSAK_HASHLEN SIPSAK_HASHLEN_SHA1
# define SIPSAK_HASHHEXLEN_SHA1 2 * SIPSAK_HASHLEN_SHA1
#else
# define SIPSAK_HASHLEN SIPSAK_HASHLEN_MD5
#endif
#define SIPSAK_HASHHEXLEN 2 * SIPSAK_HASHLEN
/* lots of global variables. ugly but makes life easier. */
unsigned long address;
unsigned int nonce_count, transport;
int sleep_ms, processes, cseq_counter;
int verbose, nameend, namebeg, expires_t, flood, warning_ext, invite, message;
int maxforw, lport, rport, randtrash, trashchar, numeric, symmetric;
int file_b, uri_b, trace, via_ins, usrloc, redirects, rand_rem, replace_b;
int empty_contact, nagios_warn, fix_crlf, timing, outbound_proxy, inv_final;
char *username, *domainname, *password, *replace_str, *hostname, *contact_uri;
char *mes_body, *con_dis, *auth_username, *from_uri, *headers;
char fqdn[FQDN_SIZE];
char target_dot[INET_ADDRSTRLEN], source_dot[INET_ADDRSTRLEN];
char *req, *rep, *rec, *transport_str;
regex_t* re;
#endif

@ -0,0 +1,585 @@
/*
* $Id:$
*
* Copyright (C) 2005 Nils Ohlmeier
*
* This file belongs to sipsak, a free sip testing tool.
*
* sipsak 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.
*
* sipsak 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.
*/
#include "sipsak.h"
#ifdef TIME_WITH_SYS_TIME
# include <sys/time.h>
# include <time.h>
#else
# ifdef HAVE_SYS_TIME_H
# include <sys/time.h>
# else
# include <time.h>
# endif
#endif /* TIME_WITH_SYS_TIME */
#ifdef HAVE_UNISTD_H
# ifdef HAVE_SYS_TYPES_H
# include <sys/types.h>
# endif
# include <unistd.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
# include <sys/socket.h>
#endif
#ifdef HAVE_SYS_POLL_H
# include <sys/poll.h>
#endif
#ifdef HAVE_ARPA_INET_H
# include <arpa/inet.h>
#endif
#include "transport.h"
#include "shoot.h"
#ifdef RAW_SUPPORT
# ifdef HAVE_NETINET_IN_SYSTM_H
# include <netinet/in_systm.h>
# endif
# ifdef HAVE_NETINET_IP_H
# include <netinet/ip.h>
# endif
# ifdef HAVE_NETINET_IP_ICMP_H
# include <netinet/ip_icmp.h>
# endif
# ifdef HAVE_NETINET_UDP_H
# define __FAVOR_BSD
# include <netinet/udp.h>
# endif
#endif /* RAW_SUPPORT */
#include "exit_code.h"
#include "helper.h"
#include "header_f.h"
#ifdef RAW_SUPPORT
int rawsock;
#endif
void create_sockets(struct sipsak_con_data *cd) {
socklen_t slen;
memset(&(cd->adr), 0, sizeof(struct sockaddr_in));
cd->adr.sin_family = AF_INET;
cd->adr.sin_addr.s_addr = htonl( INADDR_ANY);
cd->adr.sin_port = htons((short)lport);
if (transport == SIP_UDP_TRANSPORT) {
/* create the un-connected socket */
if (!symmetric) {
cd->usock = (int)socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (cd->usock==-1) {
perror("unconnected UDP socket creation failed");
exit_code(2);
}
if (bind(cd->usock, (struct sockaddr *) &(cd->adr), sizeof(struct sockaddr_in) )==-1) {
perror("unconnected UDP socket binding failed");
exit_code(2);
}
}
#ifdef RAW_SUPPORT
/* try to create the raw socket */
rawsock = (int)socket(PF_INET, SOCK_RAW, IPPROTO_ICMP);
if (rawsock==-1) {
if (verbose>1)
fprintf(stderr, "warning: need raw socket (root privileges) to receive all ICMP errors\n");
#endif
/* create the connected socket as a primitve alternative to the
raw socket*/
cd->csock = (int)socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (cd->csock==-1) {
perror("connected UDP socket creation failed");
exit_code(2);
}
if (!symmetric)
cd->adr.sin_port = htons((short)0);
if (bind(cd->csock, (struct sockaddr *) &(cd->adr), sizeof(struct sockaddr_in) )==-1) {
perror("connected UDP socket binding failed");
exit_code(2);
}
#ifdef RAW_SUPPORT
}
else if (symmetric) {
cd->csock = (int)socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (cd->csock==-1) {
perror("connected UDP socket creation failed");
exit_code(2);
}
if (bind(cd->csock, (struct sockaddr *) &(cd->adr), sizeof(struct sockaddr_in) )==-1) {
perror("connected UDP socket binding failed");
exit_code(2);
}
}
#endif
}
else {
cd->csock = (int)socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
if (cd->csock==-1) {
perror("TCP socket creation failed");
exit_code(2);
}
if (bind(cd->csock, (struct sockaddr *) &(cd->adr), sizeof(struct sockaddr_in) )==-1) {
perror("TCP socket binding failed");
exit_code(2);
}
}
/* for the via line we need our listening port number */
if (lport==0){
memset(&(cd->adr), 0, sizeof(struct sockaddr_in));
slen=sizeof(struct sockaddr_in);
if (symmetric || transport != SIP_UDP_TRANSPORT)
getsockname(cd->csock, (struct sockaddr *) &(cd->adr), &slen);
else
getsockname(cd->usock, (struct sockaddr *) &(cd->adr), &slen);
lport=ntohs(cd->adr.sin_port);
}
}
void send_message(char* mes, struct sipsak_con_data *cd,
struct sipsak_counter *sc, struct sipsak_sr_time *srt) {
struct timezone tz;
int ret;
if (cd->dontsend == 0) {
if (verbose > 2) {
printf("\nrequest:\n%s", mes);
}
/* lets fire the request to the server and store when we did */
if (cd->csock == -1) {
#ifdef DEBUG
printf("\nusing un-connected socket for sending\n");
#endif
ret = sendto(cd->usock, mes, strlen(mes), 0, (struct sockaddr *) &(cd->adr), sizeof(struct sockaddr));
}
else {
#ifdef DEBUG
printf("\nusing connected socket for sending\n");
#endif
ret = send(cd->csock, mes, strlen(mes), 0);
}
(void)gettimeofday(&(srt->sendtime), &tz);
if (ret==-1) {
if (verbose)
printf("\n");
perror("send failure");
exit_code(2);
}
#ifdef HAVE_INET_NTOP
if (verbose > 2) {
printf("\nsend to: %s:%s:%i\n", transport_str, target_dot, rport);
}
#endif
sc->send_counter++;
}
else {
cd->dontsend = 0;
}
}
void check_socket_error(int socket, int size) {
struct pollfd sockerr;
int ret = 0;
/* lets see if we at least received an icmp error */
sockerr.fd=socket;
sockerr.events=POLLERR;
ret = poll(&sockerr, 1, 10);
if (ret==1) {
if (sockerr.revents && POLLERR) {
recvfrom(socket, recv, size, 0, NULL, 0);
if (verbose)
printf("\n");
perror("send failure");
if (randtrash == 1)
printf ("last message before send failure:\n%s\n", req);
exit_code(3);
}
}
}
int check_for_message(char *recv, int size, struct sipsak_con_data *cd,
struct sipsak_sr_time *srt, struct sipsak_counter *count,
struct sipsak_delay *sd) {
fd_set fd;
struct timezone tz;
struct timeval tv;
double senddiff;
int ret = 0;
if (cd->dontrecv == 0) {
/* set the timeout and wait for a response */
tv.tv_sec = sd->retryAfter/1000;
tv.tv_usec = (sd->retryAfter % 1000) * 1000;
FD_ZERO(&fd);
if (cd->usock != -1)
FD_SET(cd->usock, &fd);
if (cd->csock != -1)
FD_SET(cd->csock, &fd);
#ifdef RAW_SUPPORT
if (rawsock != -1)
FD_SET(rawsock, &fd);
#endif
ret = select(FD_SETSIZE, &fd, NULL, NULL, &tv);
(void)gettimeofday(&(srt->recvtime), &tz);
}
else {
cd->dontrecv = 0;
}
/* store the time of our first send */
if (count->send_counter==1) {
memcpy(&(srt->firstsendt), &(srt->sendtime), sizeof(struct timeval));
}
if (sd->retryAfter == SIP_T1) {
memcpy(&(srt->starttime), &(srt->sendtime), sizeof(struct timeval));
}
if (ret == 0)
{
/* lets see if we at least received an icmp error */
if (cd->csock == -1)
check_socket_error(cd->usock, size);
else
check_socket_error(cd->csock, size);
/* printout that we did not received anything */
if (trace == 1) {
printf("%i: timeout after %i ms\n", namebeg, sd->retryAfter);
}
else if (usrloc == 1||invite == 1||message == 1) {
printf("timeout after %i ms\n", sd->retryAfter);
}
else if (verbose>0)
printf("** timeout after %i ms**\n", sd->retryAfter);
if (randtrash == 1) {
printf("did not get a response on this request:\n%s\n", req);
if (cseq_counter < nameend) {
if (count->randretrys == 2) {
printf("sended the following message three "
"times without getting a response:\n%s\n"
"give up further retransmissions...\n", req);
exit_code(3);
}
else {
printf("resending it without additional "
"random changes...\n\n");
(count->randretrys)++;
}
}
}
senddiff = deltaT(&(srt->starttime), &(srt->recvtime));
if (senddiff > inv_final) {
if (timing == 0) {
if (verbose>0)
printf("*** giving up, no final response after %.3f ms\n", senddiff);
exit_code(3);
}
else {
timing--;
count->run++;
sd->all_delay += senddiff;
sd->big_delay = senddiff;
new_transaction(req);
sd->retryAfter = SIP_T1;
if (timing == 0) {
printf("%.3f/%.3f/%.3f ms\n", sd->small_delay, sd->all_delay / count->run, sd->big_delay);
exit_code(3);
}
}
}
else {
/* set retry time according to RFC3261 */
if ((inv_trans) || (sd->retryAfter *2 < SIP_T2)) {
sd->retryAfter = sd->retryAfter * 2;
}
else {
sd->retryAfter = SIP_T2;
}
}
(count->retrans_s_c)++;
if (srt->delaytime.tv_sec == 0)
memcpy(&(srt->delaytime), &(srt->sendtime), sizeof(struct timeval));
/* if we did not exit until here lets try another send */
return -1;
}
else if ( ret == -1 ) {
perror("select error");
exit_code(2);
}
else if (((cd->usock != -1) && FD_ISSET(cd->usock, &fd)) || ((cd->csock != -1) && FD_ISSET(cd->csock, &fd))) {
if ((cd->usock != -1) && FD_ISSET(cd->usock, &fd))
ret = cd->usock;
else if ((cd->csock != -1) && FD_ISSET(cd->csock, &fd))
ret = cd->csock;
else {
printf("unable to determine the socket which received something\n");
exit_code(2);
}
/* no timeout, no error ... something has happened :-) */
if (trace == 0 && usrloc ==0 && invite == 0 && message == 0 && randtrash == 0 && (verbose > 1))
printf ("\nmessage received");
}
#ifdef RAW_SUPPORT
else if ((rawsock != -1) && FD_ISSET(rawsock, &fd)) {
if (verbose > 1)
printf("\nreceived ICMP message");
ret = rawsock;
}
#endif
else {
printf("\nselect returned succesfuly, nothing received\n");
return -1;
}
return ret;
}
int complete_mes(char *mes, int size) {
int cl = 0, headers = 0, len = 0;
char *tmp = NULL;
cl = get_cl(mes);
#ifdef DEBUG
printf("CL: %i\n", cl);
#endif
if (cl < 0){
if (verbose > 0)
printf("missing CL header; waiting for more bytes...\n");
return 0;
}
tmp = get_body(mes);
#ifdef DEBUG
printf("body: '%s'\n", tmp);
#endif
headers = tmp - mes;
#ifdef DEBUG
printf("length: %i, headers: %i\n", size, headers);
#endif
len = headers + cl;
if (len == size) {
if (verbose > 0)
printf("message is complete\n");
return 1;
}
else if (len > size) {
if (verbose > 0)
printf("waiting for more bytes...\n");
return 0;
}
else {
/* we received more then the sender claims to sent
* for now we treat this as a complete message
* FIXME: should we store the extra bytes in a buffer and
* truncate the message at the calculated length !? */
if (verbose > 0)
printf("received too much bytes...\n");
return 1;
}
}
int recv_message(char *buf, int size, int inv_trans,
struct sipsak_delay *sd, struct sipsak_sr_time *srt,
struct sipsak_counter *count, struct sipsak_con_data *cd,
struct sipsak_regexp *reg) {
int ret = 0;
int sock = 0;
double tmp_delay;
#ifdef HAVE_INET_NTOP
struct sockaddr_in peer_adr;
socklen_t psize = sizeof(peer_adr);
#endif
#ifdef RAW_SUPPORT
struct sockaddr_in faddr;
struct ip *r_ip_hdr, *s_ip_hdr;
struct icmp *icmp_hdr;
struct udphdr *udp_hdr;
size_t r_ip_len, s_ip_len, icmp_len;
int srcport, dstport;
unsigned int flen;
#endif
if (cd->buf_tmp) {
buf = cd->buf_tmp;
size = size - cd->buf_tmp_size;
}
sock = check_for_message(buf, size, cd, srt, count, sd);
if (sock <= 1) {
return -1;
}
#ifdef RAW_SUPPORT
if (sock != rawsock) {
#else
else {
#endif
check_socket_error(sock, size);
ret = recvfrom(sock, buf, size, 0, NULL, 0);
}
#ifdef RAW_SUPPORT
else {
/* lets check if the ICMP message matches with our
sent packet */
flen = sizeof(faddr);
memset(&faddr, 0, sizeof(struct sockaddr));
ret = recvfrom(rawsock, buf, size, 0, (struct sockaddr *)&faddr, &flen);
if (ret == -1) {
perror("error while trying to read from icmp raw socket");
exit_code(2);
}
r_ip_hdr = (struct ip *) buf;
r_ip_len = r_ip_hdr->ip_hl << 2;
icmp_hdr = (struct icmp *) (buf + r_ip_len);
icmp_len = ret - r_ip_len;
if (icmp_len < 8) {
if (verbose > 1)
printf(": ignoring (ICMP header length below 8 bytes)\n");
return -2;
}
else if (icmp_len < 36) {
if (verbose > 1)
printf(": ignoring (ICMP message too short to contain IP and UDP header)\n");
return -2;
}
s_ip_hdr = (struct ip *) ((char *)icmp_hdr + 8);
s_ip_len = s_ip_hdr->ip_hl << 2;
if (s_ip_hdr->ip_p == IPPROTO_UDP) {
udp_hdr = (struct udphdr *) ((char *)s_ip_hdr + s_ip_len);
srcport = ntohs(udp_hdr->uh_sport);
dstport = ntohs(udp_hdr->uh_dport);
#ifdef DEBUG
printf("\nlport: %i, rport: %i\n", lport, rport);
#endif
if ((srcport == lport) && (dstport == rport)) {
printf(" (type: %u, code: %u)", icmp_hdr->icmp_type, icmp_hdr->icmp_code);
#ifdef HAVE_INET_NTOP
if (inet_ntop(AF_INET, &faddr.sin_addr, &source_dot[0], INET_ADDRSTRLEN) != NULL)
printf(": from %s\n", source_dot);
else
printf("\n");
#else
printf("\n");
#endif // HAVE_INET_NTOP
exit_code(3);
}
else {
if (verbose > 2)
printf(": ignoring (ICMP message does not match used ports)\n");
return -2;
}
}
else {
if (verbose > 1)
printf(": ignoring (ICMP data is not a UDP packet)\n");
return -2;
}
}
#endif // RAW_SUPPORT
if (ret > 0) {
*(buf+ ret) = '\0';
if (transport != SIP_UDP_TRANSPORT) {
if (verbose > 0)
printf("\nchecking message for completness...\n");
if (complete_mes(buf, ret) == 1) {
cd->buf_tmp = NULL;
ret += cd->buf_tmp_size;
cd->buf_tmp_size = 0;
}
else {
if (cd->buf_tmp) {
cd->buf_tmp += ret;
cd->buf_tmp_size += ret;
}
else {
cd->buf_tmp = buf + ret;
cd->buf_tmp_size = ret;
}
cd->dontsend = 1;
ret = -1;
}
}
/* store the biggest delay if one occured */
if (srt->delaytime.tv_sec != 0) {
tmp_delay = deltaT(&(srt->delaytime), &(srt->recvtime));
if (tmp_delay > sd->big_delay)
sd->big_delay = tmp_delay;
if ((sd->small_delay == 0) || (tmp_delay < sd->small_delay))
sd->small_delay = tmp_delay;
srt->delaytime.tv_sec = 0;
srt->delaytime.tv_usec = 0;
}
if (timing > 0) {
tmp_delay = deltaT(&(srt->sendtime), &(srt->recvtime));
if (tmp_delay > sd->big_delay)
sd->big_delay = tmp_delay;
if ((sd->small_delay == 0) || (tmp_delay < sd->small_delay))
sd->small_delay = tmp_delay;
sd->all_delay += tmp_delay;
}
#ifdef HAVE_INET_NTOP
if ((verbose > 2) && (getpeername(sock, (struct sockaddr *)&peer_adr, &psize) == 0) && (inet_ntop(peer_adr.sin_family, &peer_adr.sin_addr, &source_dot[0], INET_ADDRSTRLEN) != NULL)) {
printf("\nreceived from: %s:%s:%i\n", transport_str,
source_dot, ntohs(peer_adr.sin_port));
}
else if (verbose > 1 && trace == 0 && usrloc == 0)
printf(":\n");
#else
if (trace == 0 && usrloc == 0)
printf(":\n");
#endif // HAVE_INET_NTOP
if (!inv_trans && ret > 0 && (regexec(&(reg->proexp), buf, 0, 0, 0) != REG_NOERROR)) {
sd->retryAfter = SIP_T1;
}
}
else {
check_socket_error(sock, size);
printf("nothing received, select returned error\n");
exit_code(2);
}
return ret;
}
/* clears the given sockaddr, fills it with the given data and if a
* socket is given connects the socket to the new target */
int set_target(struct sockaddr_in *adr, unsigned long target, int port, int socket, int connected) {
if (socket != -1 && transport != SIP_UDP_TRANSPORT && connected) {
if (shutdown(socket, SHUT_RDWR) != 0) {
perror("error while shutting down socket");
}
}
memset(adr, 0, sizeof(struct sockaddr_in));
adr->sin_addr.s_addr = target;
adr->sin_port = htons((short)port);
adr->sin_family = AF_INET;
#ifdef HAVE_INET_NTOP
inet_ntop(adr->sin_family, &adr->sin_addr, &target_dot[0], INET_ADDRSTRLEN);
#endif
if (socket != -1) {
if (connect(socket, (struct sockaddr *)adr, sizeof(struct sockaddr_in)) == -1) {
perror("connecting socket failed");
exit_code(2);
}
}
return 1;
}

@ -0,0 +1,90 @@
/*
* $Id:$
*
* Copyright (C) 2005 Nils Ohlmeier
*
* This file belongs to sipsak, a free sip testing tool.
*
* sipsak 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.
*
* sipsak 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.
*/
#ifndef SIPSAK_TRANSPORT_H
#define SIPSAK_TRANSPORT_H
#include "sipsak.h"
#include "shoot.h"
#ifdef TIME_WITH_SYS_TIME
# include <sys/time.h>
# include <time.h>
#else
# ifdef HAVE_SYS_TIME_H
# include <sys/time.h>
# else
# include <time.h>
# endif
#endif /* TIME_WITH_SYS_TIME */
#ifdef HAVE_SYS_SOCKET_H
# include <sys/socket.h>
#endif
struct sipsak_sr_time {
struct timeval sendtime;
struct timeval recvtime;
struct timeval firstsendt;
struct timeval starttime;
struct timeval delaytime;
};
struct sipsak_con_data {
struct sockaddr_in adr;
int csock;
int usock;
int dontsend;
int dontrecv;
int connected;
char *buf_tmp;
int buf_tmp_size;
};
struct sipsak_counter {
int send_counter;
int retrans_r_c;
int retrans_s_c;
int randretrys;
int run;
};
struct sipsak_delay {
int retryAfter;
double big_delay;
double small_delay;
double all_delay;
};
void create_sockets(struct sipsak_con_data *cd);
void send_message(char* mes, struct sipsak_con_data *cd,
struct sipsak_counter *sc, struct sipsak_sr_time *srt);
void check_socket_error(int socket, int size);
int check_for_message(char *recv, int size, struct sipsak_con_data *cd,
struct sipsak_sr_time *srt, struct sipsak_counter *count,
struct sipsak_delay *sd);
int recv_message(char *buf, int size, int inv_trans,
struct sipsak_delay *sd, struct sipsak_sr_time *srt,
struct sipsak_counter *count, struct sipsak_con_data *cd,
struct sipsak_regexp *reg);
int set_target(struct sockaddr_in *adr, unsigned long target, int port, int socket, int connected);
#endif
Loading…
Cancel
Save