merged in commercial subscriberRegistry
This commit is contained in:
parent
226fc1c28a
commit
25e81ce18e
|
@ -6,3 +6,7 @@
|
||||||
path = sqlite3
|
path = sqlite3
|
||||||
url = git@github.com:RangeNetworks/sqlite3.git
|
url = git@github.com:RangeNetworks/sqlite3.git
|
||||||
branch = master
|
branch = master
|
||||||
|
[submodule "NodeManager"]
|
||||||
|
path = NodeManager
|
||||||
|
url = git@github.com:RangeNetworks/NodeManager.git
|
||||||
|
branch = 4.0
|
||||||
|
|
10
COPYING
10
COPYING
|
@ -693,14 +693,6 @@ Interaction; Use with the GNU General Public License"). This exemption of
|
||||||
interfaces other than the GSM air interface from the requirements of Section 13
|
interfaces other than the GSM air interface from the requirements of Section 13
|
||||||
is an additional permission granted to you.
|
is an additional permission granted to you.
|
||||||
|
|
||||||
2. GSM "A5" cipher stream generation libraries
|
|
||||||
|
|
||||||
Notwithstanding any other provision of this License, you have
|
|
||||||
permission to link the Program with GSM "A5" cipher-stream generation
|
|
||||||
libraries provided under any license that allows redistribution of
|
|
||||||
those libraries in binary form, provided that the function of any such
|
|
||||||
library is limited to the generation of cipher-steam bits.
|
|
||||||
|
|
||||||
|
|
||||||
Non-Permissive Terms Supplementing The License
|
Non-Permissive Terms Supplementing The License
|
||||||
|
|
||||||
|
@ -712,9 +704,11 @@ license does not include the right to use the OpenBTS trademark in commerce.
|
||||||
This additional non-permissive term is consistent with Section 7 of the AGPLv3
|
This additional non-permissive term is consistent with Section 7 of the AGPLv3
|
||||||
license.
|
license.
|
||||||
|
|
||||||
|
|
||||||
END OF ADDITIONAL TERMS
|
END OF ADDITIONAL TERMS
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
How to comply with Section 13 of the AGPLv3 license.
|
How to comply with Section 13 of the AGPLv3 license.
|
||||||
|
|
||||||
The recommended method for compliance with Section 13 of the AGPLv3 license is
|
The recommended method for compliance with Section 13 of the AGPLv3 license is
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit bd94d0a9883002daa8310b601f28eed3b0d87d2f
|
Subproject commit abec8dabb69f8f2bdefdb9bcca340b89f43ce419
|
|
@ -0,0 +1,25 @@
|
||||||
|
/**@file Global system parameters. */
|
||||||
|
/*
|
||||||
|
* Copyright 2013 Range Networks, Inc.
|
||||||
|
*
|
||||||
|
* This software is distributed under multiple licenses;
|
||||||
|
* see the COPYING file in the main directory for licensing
|
||||||
|
* information for this specific distribuion.
|
||||||
|
*
|
||||||
|
* This use of this software may be subject to additional restrictions.
|
||||||
|
* See the LEGAL file in the main directory for details.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
This file keeps global system parameters.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
#include <Globals.h>
|
||||||
|
|
||||||
|
const char *gVersionString = "release " VERSION " built " __DATE__ " rev" SVN_REV " ";
|
|
@ -0,0 +1,36 @@
|
||||||
|
/**@file Global system parameters. */
|
||||||
|
/*
|
||||||
|
* Copyright 2013 Range Networks, Inc.
|
||||||
|
*
|
||||||
|
* This software is distributed under multiple licenses;
|
||||||
|
* see the COPYING file in the main directory for licensing
|
||||||
|
* information for this specific distribuion.
|
||||||
|
*
|
||||||
|
* This use of this software may be subject to additional restrictions.
|
||||||
|
* See the LEGAL file in the main directory for details.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
This file keeps global system parameters.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef GLOBALS_H
|
||||||
|
#define GLOBALS_H
|
||||||
|
|
||||||
|
#include <Configuration.h>
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Just about everything goes into the configuration table.
|
||||||
|
This should be defined in the main body of the top-level application.
|
||||||
|
*/
|
||||||
|
extern ConfigurationTable gConfig;
|
||||||
|
|
||||||
|
/** The version string. */
|
||||||
|
extern const char *gVersionString;
|
||||||
|
#endif
|
|
@ -0,0 +1,33 @@
|
||||||
|
#
|
||||||
|
# Copyright 2008 Free Software Foundation, Inc.
|
||||||
|
#
|
||||||
|
# This software is distributed under the terms of the GNU Public License.
|
||||||
|
# See the COPYING file in the main directory for details.
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
|
||||||
|
include $(top_srcdir)/Makefile.common
|
||||||
|
|
||||||
|
AM_CPPFLAGS = $(STD_DEFINES_AND_INCLUDES)
|
||||||
|
AM_CXXFLAGS = -Wall
|
||||||
|
|
||||||
|
noinst_LTLIBRARIES = libglobals.la
|
||||||
|
|
||||||
|
libglobals_la_SOURCES = Globals.cpp
|
||||||
|
|
||||||
|
noinst_PROGRAMS =
|
||||||
|
|
||||||
|
noinst_HEADERS = \
|
||||||
|
Globals.h
|
|
@ -0,0 +1,365 @@
|
||||||
|
Installation Instructions
|
||||||
|
*************************
|
||||||
|
|
||||||
|
Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005,
|
||||||
|
2006, 2007, 2008, 2009 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
Copying and distribution of this file, with or without modification,
|
||||||
|
are permitted in any medium without royalty provided the copyright
|
||||||
|
notice and this notice are preserved. This file is offered as-is,
|
||||||
|
without warranty of any kind.
|
||||||
|
|
||||||
|
Basic Installation
|
||||||
|
==================
|
||||||
|
|
||||||
|
Briefly, the shell commands `./configure; make; make install' should
|
||||||
|
configure, build, and install this package. The following
|
||||||
|
more-detailed instructions are generic; see the `README' file for
|
||||||
|
instructions specific to this package. Some packages provide this
|
||||||
|
`INSTALL' file but do not implement all of the features documented
|
||||||
|
below. The lack of an optional feature in a given package is not
|
||||||
|
necessarily a bug. More recommendations for GNU packages can be found
|
||||||
|
in *note Makefile Conventions: (standards)Makefile Conventions.
|
||||||
|
|
||||||
|
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 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.
|
||||||
|
|
||||||
|
Running `configure' might take a while. 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, generally using the just-built uninstalled binaries.
|
||||||
|
|
||||||
|
4. Type `make install' to install the programs and any data files and
|
||||||
|
documentation. When installing into a prefix owned by root, it is
|
||||||
|
recommended that the package be configured and built as a regular
|
||||||
|
user, and only the `make install' phase executed with root
|
||||||
|
privileges.
|
||||||
|
|
||||||
|
5. Optionally, type `make installcheck' to repeat any self-tests, but
|
||||||
|
this time using the binaries in their final installed location.
|
||||||
|
This target does not install anything. Running this target as a
|
||||||
|
regular user, particularly if the prior `make install' required
|
||||||
|
root privileges, verifies that the installation completed
|
||||||
|
correctly.
|
||||||
|
|
||||||
|
6. 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.
|
||||||
|
|
||||||
|
7. Often, you can also type `make uninstall' to remove the installed
|
||||||
|
files again. In practice, not all packages have tested that
|
||||||
|
uninstallation works correctly, even though it is required by the
|
||||||
|
GNU Coding Standards.
|
||||||
|
|
||||||
|
8. Some packages, particularly those that use Automake, provide `make
|
||||||
|
distcheck', which can by used by developers to test that all other
|
||||||
|
targets like `make install' and `make uninstall' work correctly.
|
||||||
|
This target is generally not run by end users.
|
||||||
|
|
||||||
|
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=c99 CFLAGS=-g 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 can use 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 `..'. This
|
||||||
|
is known as a "VPATH" build.
|
||||||
|
|
||||||
|
With a non-GNU `make', it is safer 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.
|
||||||
|
|
||||||
|
On MacOS X 10.5 and later systems, you can create libraries and
|
||||||
|
executables that work on multiple system types--known as "fat" or
|
||||||
|
"universal" binaries--by specifying multiple `-arch' options to the
|
||||||
|
compiler but only a single `-arch' option to the preprocessor. Like
|
||||||
|
this:
|
||||||
|
|
||||||
|
./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
|
||||||
|
CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
|
||||||
|
CPP="gcc -E" CXXCPP="g++ -E"
|
||||||
|
|
||||||
|
This is not guaranteed to produce working output in all cases, you
|
||||||
|
may have to build one architecture at a time and combine the results
|
||||||
|
using the `lipo' tool if you have problems.
|
||||||
|
|
||||||
|
Installation Names
|
||||||
|
==================
|
||||||
|
|
||||||
|
By default, `make install' installs the package's commands under
|
||||||
|
`/usr/local/bin', include files under `/usr/local/include', etc. You
|
||||||
|
can specify an installation prefix other than `/usr/local' by giving
|
||||||
|
`configure' the option `--prefix=PREFIX', where PREFIX must be an
|
||||||
|
absolute file name.
|
||||||
|
|
||||||
|
You can specify separate installation prefixes for
|
||||||
|
architecture-specific files and architecture-independent files. If you
|
||||||
|
pass the option `--exec-prefix=PREFIX' to `configure', the package uses
|
||||||
|
PREFIX as the prefix for installing programs and libraries.
|
||||||
|
Documentation and other data files still use the regular prefix.
|
||||||
|
|
||||||
|
In addition, if you use an unusual directory layout you can give
|
||||||
|
options like `--bindir=DIR' to specify different values for particular
|
||||||
|
kinds of files. Run `configure --help' for a list of the directories
|
||||||
|
you can set and what kinds of files go in them. In general, the
|
||||||
|
default for these options is expressed in terms of `${prefix}', so that
|
||||||
|
specifying just `--prefix' will affect all of the other directory
|
||||||
|
specifications that were not explicitly provided.
|
||||||
|
|
||||||
|
The most portable way to affect installation locations is to pass the
|
||||||
|
correct locations to `configure'; however, many packages provide one or
|
||||||
|
both of the following shortcuts of passing variable assignments to the
|
||||||
|
`make install' command line to change installation locations without
|
||||||
|
having to reconfigure or recompile.
|
||||||
|
|
||||||
|
The first method involves providing an override variable for each
|
||||||
|
affected directory. For example, `make install
|
||||||
|
prefix=/alternate/directory' will choose an alternate location for all
|
||||||
|
directory configuration variables that were expressed in terms of
|
||||||
|
`${prefix}'. Any directories that were specified during `configure',
|
||||||
|
but not in terms of `${prefix}', must each be overridden at install
|
||||||
|
time for the entire installation to be relocated. The approach of
|
||||||
|
makefile variable overrides for each directory variable is required by
|
||||||
|
the GNU Coding Standards, and ideally causes no recompilation.
|
||||||
|
However, some platforms have known limitations with the semantics of
|
||||||
|
shared libraries that end up requiring recompilation when using this
|
||||||
|
method, particularly noticeable in packages that use GNU Libtool.
|
||||||
|
|
||||||
|
The second method involves providing the `DESTDIR' variable. For
|
||||||
|
example, `make install DESTDIR=/alternate/directory' will prepend
|
||||||
|
`/alternate/directory' before all installation names. The approach of
|
||||||
|
`DESTDIR' overrides is not required by the GNU Coding Standards, and
|
||||||
|
does not work on platforms that have drive letters. On the other hand,
|
||||||
|
it does better at avoiding recompilation issues, and works well even
|
||||||
|
when some directory options were not specified in terms of `${prefix}'
|
||||||
|
at `configure' time.
|
||||||
|
|
||||||
|
Optional Features
|
||||||
|
=================
|
||||||
|
|
||||||
|
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'.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
Some packages offer the ability to configure how verbose the
|
||||||
|
execution of `make' will be. For these packages, running `./configure
|
||||||
|
--enable-silent-rules' sets the default to minimal output, which can be
|
||||||
|
overridden with `make V=1'; while running `./configure
|
||||||
|
--disable-silent-rules' sets the default to verbose, which can be
|
||||||
|
overridden with `make V=0'.
|
||||||
|
|
||||||
|
Particular systems
|
||||||
|
==================
|
||||||
|
|
||||||
|
On HP-UX, the default C compiler is not ANSI C compatible. If GNU
|
||||||
|
CC is not installed, it is recommended to use the following options in
|
||||||
|
order to use an ANSI C compiler:
|
||||||
|
|
||||||
|
./configure CC="cc -Ae -D_XOPEN_SOURCE=500"
|
||||||
|
|
||||||
|
and if that doesn't work, install pre-built binaries of GCC for HP-UX.
|
||||||
|
|
||||||
|
On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot
|
||||||
|
parse its `<wchar.h>' header file. The option `-nodtk' can be used as
|
||||||
|
a workaround. If GNU CC is not installed, it is therefore recommended
|
||||||
|
to try
|
||||||
|
|
||||||
|
./configure CC="cc"
|
||||||
|
|
||||||
|
and if that doesn't work, try
|
||||||
|
|
||||||
|
./configure CC="cc -nodtk"
|
||||||
|
|
||||||
|
On Solaris, don't put `/usr/ucb' early in your `PATH'. This
|
||||||
|
directory contains several dysfunctional programs; working variants of
|
||||||
|
these programs are available in `/usr/bin'. So, if you need `/usr/ucb'
|
||||||
|
in your `PATH', put it _after_ `/usr/bin'.
|
||||||
|
|
||||||
|
On Haiku, software installed for all users goes in `/boot/common',
|
||||||
|
not `/usr/local'. It is recommended to use the following options:
|
||||||
|
|
||||||
|
./configure --prefix=/boot/common
|
||||||
|
|
||||||
|
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 option `--target=TYPE' to select the type of system they will
|
||||||
|
produce code for.
|
||||||
|
|
||||||
|
If you want to _use_ a cross compiler, that generates code for a
|
||||||
|
platform different from the build platform, you should specify the
|
||||||
|
"host" platform (i.e., that on which the generated programs will
|
||||||
|
eventually be run) with `--host=TYPE'.
|
||||||
|
|
||||||
|
Sharing Defaults
|
||||||
|
================
|
||||||
|
|
||||||
|
If you want to set default values for `configure' scripts to share,
|
||||||
|
you can create a site shell script called `config.site' that gives
|
||||||
|
default values for variables like `CC', `cache_file', and `prefix'.
|
||||||
|
`configure' looks for `PREFIX/share/config.site' if it exists, then
|
||||||
|
`PREFIX/etc/config.site' if it exists. Or, you can set the
|
||||||
|
`CONFIG_SITE' environment variable to the location of the site script.
|
||||||
|
A warning: not all `configure' scripts look for a site script.
|
||||||
|
|
||||||
|
Defining Variables
|
||||||
|
==================
|
||||||
|
|
||||||
|
Variables not defined in a site shell script can be set in the
|
||||||
|
environment passed to `configure'. However, some packages may run
|
||||||
|
configure again during the build, and the customized values of these
|
||||||
|
variables may be lost. In order to avoid this problem, you should set
|
||||||
|
them in the `configure' command line, using `VAR=value'. For example:
|
||||||
|
|
||||||
|
./configure CC=/usr/local2/bin/gcc
|
||||||
|
|
||||||
|
causes the specified `gcc' to be used as the C compiler (unless it is
|
||||||
|
overridden in the site shell script).
|
||||||
|
|
||||||
|
Unfortunately, this technique does not work for `CONFIG_SHELL' due to
|
||||||
|
an Autoconf bug. Until the bug is fixed you can use this workaround:
|
||||||
|
|
||||||
|
CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash
|
||||||
|
|
||||||
|
`configure' Invocation
|
||||||
|
======================
|
||||||
|
|
||||||
|
`configure' recognizes the following options to control how it
|
||||||
|
operates.
|
||||||
|
|
||||||
|
`--help'
|
||||||
|
`-h'
|
||||||
|
Print a summary of all of the options to `configure', and exit.
|
||||||
|
|
||||||
|
`--help=short'
|
||||||
|
`--help=recursive'
|
||||||
|
Print a summary of the options unique to this package's
|
||||||
|
`configure', and exit. The `short' variant lists options used
|
||||||
|
only in the top level, while the `recursive' variant lists options
|
||||||
|
also present in any nested packages.
|
||||||
|
|
||||||
|
`--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.
|
||||||
|
|
||||||
|
`--prefix=DIR'
|
||||||
|
Use DIR as the installation prefix. *note Installation Names::
|
||||||
|
for more details, including other options available for fine-tuning
|
||||||
|
the installation locations.
|
||||||
|
|
||||||
|
`--no-create'
|
||||||
|
`-n'
|
||||||
|
Run the configure checks, but stop before creating any output
|
||||||
|
files.
|
||||||
|
|
||||||
|
`configure' also accepts some other, not widely useful, options. Run
|
||||||
|
`configure --help' for more details.
|
||||||
|
|
61
Makefile
61
Makefile
|
@ -1,61 +0,0 @@
|
||||||
COM=CommonLibs
|
|
||||||
SQL=sqlite3
|
|
||||||
SR=.
|
|
||||||
LOCALLIBS=$(COM)/Logger.cpp $(COM)/Timeval.cpp $(COM)/Threads.cpp $(COM)/Sockets.cpp $(COM)/Configuration.cpp $(COM)/sqlite3util.cpp $(SR)/SubscriberRegistry.cpp $(COM)/Utils.cpp servershare.cpp
|
|
||||||
LIBS= -L$(SQL) $(LOCALLIBS) -losipparser2 -losip2 -lc -lpthread -lsqlite3
|
|
||||||
INCLUDES=-I$(COM) -I$(SQL) -I$(SR)
|
|
||||||
CPPFLAGS=-g -Wall -Wno-deprecated
|
|
||||||
|
|
||||||
DESTDIR :=
|
|
||||||
|
|
||||||
all: comp128 srmanager.cgi subscriberserver.cgi sipauthserve
|
|
||||||
|
|
||||||
comp128: comp128.c
|
|
||||||
g++ -o comp128 comp128.c
|
|
||||||
|
|
||||||
subscriberserver.cgi: subscriberserver.cpp $(LOCALLIBS)
|
|
||||||
g++ -o subscriberserver.cgi $(CPPFLAGS) $(INCLUDES) subscriberserver.cpp $(LIBS)
|
|
||||||
|
|
||||||
srmanager.cgi: srmanager.cpp $(LOCALLIBS)
|
|
||||||
g++ -o srmanager.cgi $(CPPFLAGS) $(INCLUDES) srmanager.cpp $(LIBS)
|
|
||||||
|
|
||||||
sipauthserve: sipauthserve.cpp $(LOCALLIBS)
|
|
||||||
g++ -o sipauthserve $(CPPFLAGS) $(INCLUDES) sipauthserve.cpp $(LIBS)
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -f comp128 subscriberserver.cgi srmanager.cgi sipauthserve test.SubscriberRegistry/test
|
|
||||||
rm -r -f *.dSYM
|
|
||||||
|
|
||||||
# this needs "local7.debug<at least one tab>/var/log/openbts.log" in /etc/syslog.conf
|
|
||||||
test: all
|
|
||||||
cd test.SubscriberRegistry; ./runtest
|
|
||||||
cd test.sipauthserve; ./runtest
|
|
||||||
cd test.srmanager; ./runtest
|
|
||||||
cd test.subscriberserver; ./runtest
|
|
||||||
|
|
||||||
just3: all
|
|
||||||
cd test.SubscriberRegistry; ./runtest
|
|
||||||
cd test.srmanager; ./runtest
|
|
||||||
cd test.subscriberserver; ./runtest
|
|
||||||
|
|
||||||
IPATH=$(DESTDIR)/usr/local/bin/
|
|
||||||
CGIPATH=$(DESTDIR)/var/cgi-bin/
|
|
||||||
OPATH=$(DESTDIR)/OpenBTS/
|
|
||||||
CONFIGPATH=$(DESTDIR)/etc/OpenBTS/
|
|
||||||
|
|
||||||
# specifically for boa web server
|
|
||||||
install: all
|
|
||||||
mkdir -p $(IPATH)
|
|
||||||
install comp128 $(IPATH)
|
|
||||||
install hexmapper $(IPATH)
|
|
||||||
install syslogextractor $(IPATH)
|
|
||||||
mkdir -p $(CGIPATH)
|
|
||||||
install -m +s -o root srmanager.cgi $(CGIPATH)
|
|
||||||
install -m +s -o root subscriberserver.cgi $(CGIPATH)
|
|
||||||
mkdir -p $(OPATH)
|
|
||||||
install comp128 $(OPATH)
|
|
||||||
install sipauthserve $(OPATH)
|
|
||||||
install runloop.sipauthserve.sh $(OPATH)
|
|
||||||
mkdir -p $(CONFIGPATH)
|
|
||||||
install subscriberRegistry.example.sql $(CONFIGPATH)
|
|
||||||
|
|
25
Makefile.am
25
Makefile.am
|
@ -1,6 +1,5 @@
|
||||||
#
|
#
|
||||||
# Copyright 2009 Free Software Foundation, Inc.
|
# Copyright 2008 Free Software Foundation, Inc.
|
||||||
# Copyright 2010 Kestrel Signal Processing, Inc.
|
|
||||||
#
|
#
|
||||||
# This software is distributed under the terms of the GNU Public License.
|
# This software is distributed under the terms of the GNU Public License.
|
||||||
# See the COPYING file in the main directory for details.
|
# See the COPYING file in the main directory for details.
|
||||||
|
@ -21,8 +20,10 @@
|
||||||
|
|
||||||
include $(top_srcdir)/Makefile.common
|
include $(top_srcdir)/Makefile.common
|
||||||
|
|
||||||
AM_CPPFLAGS = $(STD_DEFINES_AND_INCLUDES)
|
DESTDIR :=
|
||||||
AM_CXXFLAGS = $(STD_DEFINES_AND_INCLUDES) -Wall -ldl -lpthread
|
|
||||||
|
AM_CPPFLAGS = $(STD_DEFINES_AND_INCLUDES) $(WITH_INCLUDES)
|
||||||
|
AM_CXXFLAGS = -Wall -pthread -ldl
|
||||||
|
|
||||||
noinst_LTLIBRARIES = libSR.la
|
noinst_LTLIBRARIES = libSR.la
|
||||||
|
|
||||||
|
@ -32,3 +33,19 @@ libSR_la_SOURCES = \
|
||||||
noinst_HEADERS = \
|
noinst_HEADERS = \
|
||||||
SubscriberRegistry.h
|
SubscriberRegistry.h
|
||||||
|
|
||||||
|
# Order must be preserved
|
||||||
|
SUBDIRS = \
|
||||||
|
config \
|
||||||
|
sqlite3 \
|
||||||
|
CommonLibs \
|
||||||
|
Globals \
|
||||||
|
NodeManager \
|
||||||
|
apps
|
||||||
|
|
||||||
|
install: all
|
||||||
|
$(MAKE) -C ./apps install
|
||||||
|
|
||||||
|
dox: FORCE
|
||||||
|
doxygen doxconfig
|
||||||
|
|
||||||
|
FORCE:
|
||||||
|
|
|
@ -0,0 +1,48 @@
|
||||||
|
#
|
||||||
|
# Copyright 2008 Free Software Foundation, Inc.
|
||||||
|
#
|
||||||
|
# This software is distributed under the terms of the GNU Public License.
|
||||||
|
# See the COPYING file in the main directory for details.
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
|
||||||
|
AM_CPPFLAGS = $(STD_DEFINES_AND_INCLUDES) $(WITH_INCLUDES)
|
||||||
|
AM_CXXFLAGS = -Wall -pthread -ldl
|
||||||
|
|
||||||
|
COMMON_INCLUDEDIR = $(top_srcdir)/CommonLibs
|
||||||
|
GLOBALS_INCLUDEDIR = $(top_srcdir)/Globals
|
||||||
|
SQLITE_INCLUDEDIR = $(top_srcdir)/sqlite3
|
||||||
|
NODEMANAGER_INCLUDEDIR = $(top_srcdir)/NodeManager
|
||||||
|
JSONBOX_INCLUDEDIR = $(top_srcdir)/NodeManager/JsonBox-0.4.3/include
|
||||||
|
JSONDB_INCLUDEDIR = $(top_srcdir)/NodeManager/JSONDB
|
||||||
|
|
||||||
|
SVNDEV = -D'SVN_REV="$(shell svn info $(top_builddir) | grep "Last Changed Rev:" | cut -d " " -f 4) CommonLibs:rev$(shell svn info $(top_builddir)/CommonLibs | grep "Last Changed Rev:" | cut -d " " -f 4)"'
|
||||||
|
|
||||||
|
STD_DEFINES_AND_INCLUDES = \
|
||||||
|
$(SVNDEV) \
|
||||||
|
-I$(COMMON_INCLUDEDIR) \
|
||||||
|
-I$(GLOBALS_INCLUDEDIR) \
|
||||||
|
-I$(NODEMANAGER_INCLUDEDIR) \
|
||||||
|
-I$(JSONBOX_INCLUDEDIR) \
|
||||||
|
-I$(JSONDB_INCLUDEDIR) \
|
||||||
|
-I$(SQLITE_INCLUDEDIR)
|
||||||
|
|
||||||
|
# These macros are referenced in apps/Makefile.am, which must be changed in sync with these.
|
||||||
|
COMMON_LA = $(top_builddir)/CommonLibs/libcommon.la
|
||||||
|
GLOBALS_LA = $(top_builddir)/Globals/libglobals.la
|
||||||
|
NODEMANAGER_LA = $(top_builddir)/NodeManager/libnodemanager.la -lzmq
|
||||||
|
SQLITE_LA = $(top_builddir)/sqlite3/libsqlite.la -ldl
|
||||||
|
|
||||||
|
MOSTLYCLEANFILES = *~
|
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit c154368a55d081d7be241a14825e9a009dee093a
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2011 Kestrel Signal Processing, Inc.
|
* Copyright 2011 Kestrel Signal Processing, Inc.
|
||||||
* Copyright 2011, 2012 Range Networks, Inc.
|
* Copyright 2011, 2012, 2013, 2014 Range Networks, Inc.
|
||||||
*
|
*
|
||||||
* This software is distributed under the terms of the GNU Affero Public License.
|
* This software is distributed under the terms of the GNU Affero Public License.
|
||||||
* See the COPYING file in the main directory for details.
|
* See the COPYING file in the main directory for details.
|
||||||
|
@ -33,6 +33,7 @@
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
#include <algorithm> // for sort()
|
||||||
#include <Configuration.h>
|
#include <Configuration.h>
|
||||||
|
|
||||||
extern ConfigurationTable gConfig;
|
extern ConfigurationTable gConfig;
|
||||||
|
@ -157,6 +158,15 @@ static const char* createSBTable = {
|
||||||
")"
|
")"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const char* createMEMSBTable = {
|
||||||
|
"CREATE TABLE IF NOT EXISTS memcache.mem_sip_buddies ("
|
||||||
|
"username varchar(80) primary key, "
|
||||||
|
"ipaddr varchar(45), "
|
||||||
|
"port int(5) default 5062, "
|
||||||
|
"rand varchar(33) default '', "
|
||||||
|
"sres varchar(33) default ''"
|
||||||
|
")"
|
||||||
|
};
|
||||||
|
|
||||||
int SubscriberRegistry::init()
|
int SubscriberRegistry::init()
|
||||||
{
|
{
|
||||||
|
@ -202,10 +212,243 @@ int SubscriberRegistry::init()
|
||||||
if (!sqlite3_command(mDB,enableWAL,mNumSQLTries)) {
|
if (!sqlite3_command(mDB,enableWAL,mNumSQLTries)) {
|
||||||
LOG(EMERG) << "Cannot enable WAL mode on database at " << ldb << ", error message: " << sqlite3_errmsg(mDB);
|
LOG(EMERG) << "Cannot enable WAL mode on database at " << ldb << ", error message: " << sqlite3_errmsg(mDB);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef SR_API_ONLY
|
||||||
|
// memory based sip_buddies table
|
||||||
|
if (!sqlite3_command(mDB,"attach database ':memory:' as memcache",mNumSQLTries)) {
|
||||||
|
LOG(EMERG) << "Cannot create memcache database";
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (!sqlite3_command(mDB,createMEMSBTable,mNumSQLTries)) {
|
||||||
|
LOG(EMERG) << "Cannot create memcache mem_sip_buddies table";
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (!sqlite3_command(mDB,"INSERT INTO mem_sip_buddies SELECT username, ipaddr, port, rand, sres FROM sip_buddies",mNumSQLTries)) {
|
||||||
|
LOG(EMERG) << "Cannot populate mem_sip_buddies table with disk contents";
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (!sqlite3_command(mDB,"ALTER TABLE mem_sip_buddies ADD dirty INTEGER DEFAULT 0",mNumSQLTries)) {
|
||||||
|
LOG(EMERG) << "Cannot add dirty column to mem_sip_buddies table";
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start the sync thread
|
||||||
|
mSyncer.start((void*(*)(void*))subscriberRegistrySyncer,NULL);
|
||||||
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string SubscriberRegistry::getResultsAsString(string query)
|
||||||
|
{
|
||||||
|
sqlite3_stmt *stmt;
|
||||||
|
|
||||||
|
if (sqlite3_prepare_statement(mDB, &stmt, query.c_str(), 5)) {
|
||||||
|
std::cout << " - sqlite3_prepare_statement() failed" << std::endl;
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
int state;
|
||||||
|
int row = 0;
|
||||||
|
int col;
|
||||||
|
int colMax = sqlite3_column_count(stmt);
|
||||||
|
const char* colName;
|
||||||
|
const char* colText;
|
||||||
|
ostringstream colNames;
|
||||||
|
ostringstream colTexts;
|
||||||
|
while (1) {
|
||||||
|
state = sqlite3_step(stmt);
|
||||||
|
if (state == SQLITE_ROW) {
|
||||||
|
for (col = 0; col < colMax; col++) {
|
||||||
|
colName = (const char*)sqlite3_column_name(stmt, col);
|
||||||
|
colText = (const char*)sqlite3_column_text(stmt, col);
|
||||||
|
|
||||||
|
if (row == 0) {
|
||||||
|
colNames << colName << " ";
|
||||||
|
}
|
||||||
|
if (colText == NULL) {
|
||||||
|
colTexts << "NULL" << " ";
|
||||||
|
} else {
|
||||||
|
colTexts << colText << " ";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (state == SQLITE_DONE) {
|
||||||
|
break;
|
||||||
|
// TODO : handle more SQLITE_FAILURECODES here
|
||||||
|
} else {
|
||||||
|
return " - failed in while(1) in } else {";
|
||||||
|
}
|
||||||
|
colTexts << std::endl;
|
||||||
|
row++;
|
||||||
|
}
|
||||||
|
sqlite3_finalize(stmt);
|
||||||
|
|
||||||
|
ostringstream s;
|
||||||
|
string title = colNames.str();
|
||||||
|
if (title.length()) {
|
||||||
|
s << title << std::endl;
|
||||||
|
s << colTexts << std::endl;
|
||||||
|
} else {
|
||||||
|
s << " - none found" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
return s.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
vector<string> SubscriberRegistry::getTableColumns(string tableName)
|
||||||
|
{
|
||||||
|
vector<string> colNames;
|
||||||
|
stringstream tmp;
|
||||||
|
tmp << "select * from " << tableName << " limit 1";
|
||||||
|
|
||||||
|
sqlite3_stmt *stmt;
|
||||||
|
|
||||||
|
if (sqlite3_prepare_statement(mDB, &stmt, tmp.str().c_str(), 5)) {
|
||||||
|
std::cout << " - getTableColumns() - sqlite3_prepare_statement() failed" << std::endl;
|
||||||
|
return colNames;
|
||||||
|
}
|
||||||
|
tmp.str("");
|
||||||
|
|
||||||
|
int state;
|
||||||
|
int col;
|
||||||
|
int colMax = sqlite3_column_count(stmt);
|
||||||
|
while (1) {
|
||||||
|
state = sqlite3_step(stmt);
|
||||||
|
if (state == SQLITE_ROW) {
|
||||||
|
for (col = 0; col < colMax; col++) {
|
||||||
|
tmp << (const char*)sqlite3_column_name(stmt, col);
|
||||||
|
colNames.push_back(tmp.str());
|
||||||
|
tmp.str("");
|
||||||
|
}
|
||||||
|
} else if (state == SQLITE_DONE) {
|
||||||
|
break;
|
||||||
|
// TODO : handle more SQLITE_FAILURECODES here
|
||||||
|
} else {
|
||||||
|
std::cout << " - getTableColumns() - failed in while(1) in } else {" << std::endl;
|
||||||
|
return colNames;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sqlite3_finalize(stmt);
|
||||||
|
|
||||||
|
return colNames;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef SR_API_ONLY
|
||||||
|
string SubscriberRegistry::generateSyncToDiskQuery()
|
||||||
|
{
|
||||||
|
vector<string> columns = getTableColumns("sip_buddies");
|
||||||
|
if (!columns.size()) {
|
||||||
|
LOG(DEBUG) << "sip_buddies is empty";
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
sort(columns.begin(), columns.end());
|
||||||
|
std::stringstream ss;
|
||||||
|
unsigned i;
|
||||||
|
|
||||||
|
ss << "replace into sip_buddies (ipaddr, port, rand, sres, ";
|
||||||
|
|
||||||
|
for (i = 0; i < columns.size(); i++) {
|
||||||
|
if (columns[i].compare("ipaddr") == 0 || columns[i].compare("port") == 0 ||
|
||||||
|
columns[i].compare("rand") == 0 || columns[i].compare("sres") == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (i != 0) {
|
||||||
|
ss << ", ";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (columns[i].find("-") != std::string::npos) {
|
||||||
|
ss << "'" << columns[i] << "'";
|
||||||
|
} else {
|
||||||
|
ss << columns[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ss << ") select src.ipaddr, src.port, src.rand, src.sres, ";
|
||||||
|
|
||||||
|
for (i = 0; i < columns.size(); i++) {
|
||||||
|
if (columns[i].compare("ipaddr") == 0 || columns[i].compare("port") == 0 ||
|
||||||
|
columns[i].compare("rand") == 0 || columns[i].compare("sres") == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (i != 0) {
|
||||||
|
ss << ", ";
|
||||||
|
}
|
||||||
|
|
||||||
|
ss << "dest.";
|
||||||
|
if (columns[i].find("-") != std::string::npos) {
|
||||||
|
ss << "'" << columns[i] << "'";
|
||||||
|
} else {
|
||||||
|
ss << columns[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ss << " from mem_sip_buddies src ";
|
||||||
|
ss << "inner join sip_buddies dest on src.username = dest.username ";
|
||||||
|
ss << "where src.dirty = \"1\"";
|
||||||
|
|
||||||
|
return ss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SubscriberRegistry::syncMemoryDB()
|
||||||
|
{
|
||||||
|
bool ret = true;
|
||||||
|
string syncToDisk = generateSyncToDiskQuery();
|
||||||
|
|
||||||
|
string cleanDirty = "update mem_sip_buddies set dirty = \"0\"";
|
||||||
|
|
||||||
|
string syncFromDiskAddNewEntries = "INSERT INTO mem_sip_buddies "
|
||||||
|
"(username, ipaddr, port, rand, sres, dirty) "
|
||||||
|
"SELECT sip_buddies.username, sip_buddies.ipaddr, sip_buddies.port, sip_buddies.rand, sip_buddies.sres, '0' FROM sip_buddies "
|
||||||
|
"LEFT OUTER JOIN mem_sip_buddies ON (mem_sip_buddies.username=sip_buddies.username) "
|
||||||
|
"WHERE mem_sip_buddies.username IS NULL";
|
||||||
|
|
||||||
|
string syncFromDiskDeleteOldEntries = "DELETE FROM mem_sip_buddies "
|
||||||
|
"WHERE username IN "
|
||||||
|
"(SELECT mem_sip_buddies.username FROM mem_sip_buddies"
|
||||||
|
" LEFT JOIN sip_buddies ON mem_sip_buddies.username=sip_buddies.username"
|
||||||
|
" WHERE sip_buddies.username IS NULL"
|
||||||
|
")";
|
||||||
|
|
||||||
|
Timeval timer;
|
||||||
|
mLock.lock();
|
||||||
|
|
||||||
|
// this string is only non-empty if there are entries in sip_buddies
|
||||||
|
if (syncToDisk.length()) {
|
||||||
|
// sync dirty entries to disk
|
||||||
|
if (sqlUpdate(syncToDisk.c_str()) == FAILURE) {
|
||||||
|
LOG(ERR) << "syncToDisk failed";
|
||||||
|
} else {
|
||||||
|
// if it succeeds, mark these entries as clean again
|
||||||
|
LOG(INFO) << "syncToDisk succeeded";
|
||||||
|
if (sqlUpdate(cleanDirty.c_str()) == FAILURE) {
|
||||||
|
LOG(ERR) << "cleanDirty failed";
|
||||||
|
} else {
|
||||||
|
LOG(INFO) << "cleanDirty succeeded";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// sync new rows from the disk into memory
|
||||||
|
if (sqlUpdate(syncFromDiskAddNewEntries.c_str()) == FAILURE) {
|
||||||
|
LOG(ERR) << "syncFromDiskAddNewEntries failed";
|
||||||
|
} else {
|
||||||
|
LOG(INFO) << "syncFromDiskAddNewEntries succeeded";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// delete old entries from memory no longer found on the disk
|
||||||
|
if (sqlUpdate(syncFromDiskDeleteOldEntries.c_str()) == FAILURE) {
|
||||||
|
LOG(ERR) << "syncFromDiskDeleteOldEntries failed";
|
||||||
|
} else {
|
||||||
|
LOG(INFO) << "syncFromDiskDeleteOldEntries succeeded";
|
||||||
|
}
|
||||||
|
|
||||||
|
mLock.unlock();
|
||||||
|
LOG(INFO) << "syncMemoryDB() locked the db for " << timer.elapsed() << "ms";
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
SubscriberRegistry::~SubscriberRegistry()
|
SubscriberRegistry::~SubscriberRegistry()
|
||||||
{
|
{
|
||||||
|
@ -214,20 +457,6 @@ SubscriberRegistry::~SubscriberRegistry()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
SubscriberRegistry::Status SubscriberRegistry::sqlHttp(const char *stmt, char **resultptr)
|
|
||||||
{
|
|
||||||
LOG(INFO) << stmt;
|
|
||||||
HttpQuery qry("sql");
|
|
||||||
qry.send("stmts", stmt);
|
|
||||||
if (!qry.http(false)) return FAILURE;
|
|
||||||
const char *res = qry.receive("res");
|
|
||||||
if (!res) return FAILURE;
|
|
||||||
*resultptr = strdup(res);
|
|
||||||
return SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
SubscriberRegistry::Status SubscriberRegistry::sqlLocal(const char *query, char **resultptr)
|
SubscriberRegistry::Status SubscriberRegistry::sqlLocal(const char *query, char **resultptr)
|
||||||
{
|
{
|
||||||
LOG(INFO) << query;
|
LOG(INFO) << query;
|
||||||
|
@ -273,19 +502,7 @@ char *SubscriberRegistry::sqlQuery(const char *unknownColumn, const char *table,
|
||||||
LOG(INFO) << "result = " << result;
|
LOG(INFO) << "result = " << result;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
// didn't find locally, so try over http
|
// didn't find locally
|
||||||
st = sqlHttp(os.str().c_str(), &result);
|
|
||||||
if ((st == SUCCESS) && result) {
|
|
||||||
// found over http but not locally, so cache locally
|
|
||||||
ostringstream os2;
|
|
||||||
os2 << "insert into " << table << "(" << knownColumn << ", " << unknownColumn << ") values (\"" <<
|
|
||||||
knownValue << "\",\"" << result << "\")";
|
|
||||||
// ignore whether it succeeds
|
|
||||||
sqlLocal(os2.str().c_str(), NULL);
|
|
||||||
LOG(INFO) << "result = " << result;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
// didn't find locally or over http
|
|
||||||
LOG(INFO) << "not found: " << os.str();
|
LOG(INFO) << "not found: " << os.str();
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -295,32 +512,48 @@ char *SubscriberRegistry::sqlQuery(const char *unknownColumn, const char *table,
|
||||||
SubscriberRegistry::Status SubscriberRegistry::sqlUpdate(const char *stmt)
|
SubscriberRegistry::Status SubscriberRegistry::sqlUpdate(const char *stmt)
|
||||||
{
|
{
|
||||||
LOG(INFO) << stmt;
|
LOG(INFO) << stmt;
|
||||||
SubscriberRegistry::Status st = sqlLocal(stmt, NULL);
|
return sqlLocal(stmt, NULL);
|
||||||
sqlHttp(stmt, NULL);
|
|
||||||
// status of local is only important one because asterisk talks to that db directly
|
|
||||||
// must update local no matter what
|
|
||||||
return st;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
string SubscriberRegistry::imsiGet(string imsi, string key)
|
string SubscriberRegistry::imsiGet(string imsi, string key)
|
||||||
{
|
{
|
||||||
string name = imsi.substr(0,4) == "IMSI" ? imsi : "IMSI" + imsi;
|
string name = imsi.substr(0,4) == "IMSI" ? imsi : "IMSI" + imsi;
|
||||||
char *st = sqlQuery(key.c_str(), "sip_buddies", "name", imsi.c_str());
|
char *st = sqlQuery(key.c_str(), "sip_buddies", "username", name.c_str());
|
||||||
if (!st) {
|
if (!st) {
|
||||||
LOG(WARNING) << "cannot get key " << key << " for username " << imsi;
|
LOG(INFO) << "cannot get key " << key << " for username " << name;
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
return st;
|
return st;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef SR_API_ONLY
|
||||||
bool SubscriberRegistry::imsiSet(string imsi, string key, string value)
|
bool SubscriberRegistry::imsiSet(string imsi, string key, string value)
|
||||||
{
|
{
|
||||||
string name = imsi.substr(0,4) == "IMSI" ? imsi : "IMSI" + imsi;
|
string name = imsi.substr(0,4) == "IMSI" ? imsi : "IMSI" + imsi;
|
||||||
ostringstream os;
|
ostringstream os;
|
||||||
os << "update sip_buddies set " << key << " = \"" << value << "\" where name = \"" << name << "\"";
|
os << "update mem_sip_buddies set dirty = \"1\", " << key << " = \"" << value << "\" where username = \"" << name << "\"";
|
||||||
return sqlUpdate(os.str().c_str()) == FAILURE;
|
|
||||||
|
mLock.lock();
|
||||||
|
SubscriberRegistry::Status ret = sqlUpdate(os.str().c_str());
|
||||||
|
mLock.unlock();
|
||||||
|
|
||||||
|
return ret == FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SubscriberRegistry::imsiSet(string imsi, string key1, string value1, string key2, string value2)
|
||||||
|
{
|
||||||
|
string name = imsi.substr(0,4) == "IMSI" ? imsi : "IMSI" + imsi;
|
||||||
|
ostringstream os;
|
||||||
|
os << "update mem_sip_buddies set dirty = \"1\", " << key1 << " = \"" << value1 << "\"," << key2 << " = \"" << value2 << "\" where username = \"" << name << "\"";
|
||||||
|
|
||||||
|
mLock.lock();
|
||||||
|
SubscriberRegistry::Status ret = sqlUpdate(os.str().c_str());
|
||||||
|
mLock.unlock();
|
||||||
|
|
||||||
|
return ret == FAILURE;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
char *SubscriberRegistry::getIMSI(const char *ISDN)
|
char *SubscriberRegistry::getIMSI(const char *ISDN)
|
||||||
{
|
{
|
||||||
if (!ISDN) {
|
if (!ISDN) {
|
||||||
|
@ -431,34 +664,6 @@ SubscriberRegistry::Status SubscriberRegistry::addUser(const char* IMSI, const c
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// For handover. Only remove the local cache. BS2 will have updated the global.
|
|
||||||
SubscriberRegistry::Status SubscriberRegistry::removeUser(const char* IMSI)
|
|
||||||
{
|
|
||||||
if (!IMSI) {
|
|
||||||
LOG(WARNING) << "SubscriberRegistry::addUser attempting add of NULL IMSI";
|
|
||||||
return FAILURE;
|
|
||||||
}
|
|
||||||
LOG(INFO) << "removeUser(" << IMSI << ")";
|
|
||||||
string server = gConfig.getStr("SubscriberRegistry.UpstreamServer");
|
|
||||||
if (server.length() == 0) {
|
|
||||||
LOG(INFO) << "not removing user if no upstream server";
|
|
||||||
return FAILURE;
|
|
||||||
}
|
|
||||||
ostringstream os;
|
|
||||||
os << "delete from sip_buddies where name = ";
|
|
||||||
os << "\"" << IMSI << "\"";
|
|
||||||
os << ";";
|
|
||||||
LOG(INFO) << os.str();
|
|
||||||
SubscriberRegistry::Status st = sqlLocal(os.str().c_str(), NULL);
|
|
||||||
ostringstream os2;
|
|
||||||
os2 << "delete from dialdata_table where dial = ";
|
|
||||||
os2 << "\"" << IMSI << "\"";
|
|
||||||
LOG(INFO) << os2.str();
|
|
||||||
SubscriberRegistry::Status st2 = sqlLocal(os2.str().c_str(), NULL);
|
|
||||||
return st == SUCCESS && st2 == SUCCESS ? SUCCESS : FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
char *SubscriberRegistry::mapCLIDGlobal(const char *local)
|
char *SubscriberRegistry::mapCLIDGlobal(const char *local)
|
||||||
{
|
{
|
||||||
|
@ -487,307 +692,17 @@ SubscriberRegistry::Status SubscriberRegistry::RRLPUpdate(string name, string la
|
||||||
return sqlUpdate(os.str().c_str());
|
return sqlUpdate(os.str().c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef SR_API_ONLY
|
||||||
|
extern SubscriberRegistry gSubscriberRegistry;
|
||||||
string SubscriberRegistry::getRandForAuthentication(bool sip, string IMSI)
|
void* subscriberRegistrySyncer(void*)
|
||||||
{
|
{
|
||||||
if (IMSI.length() == 0) {
|
while (true) {
|
||||||
LOG(WARNING) << "SubscriberRegistry::getRandForAuthentication attempting lookup of NULL IMSI";
|
sleep(15);
|
||||||
return "";
|
gSubscriberRegistry.syncMemoryDB();
|
||||||
}
|
|
||||||
LOG(INFO) << "getRandForAuthentication(" << IMSI << ")";
|
|
||||||
// get rand from SR server
|
|
||||||
HttpQuery qry("rand");
|
|
||||||
qry.send("imsi", IMSI);
|
|
||||||
qry.log();
|
|
||||||
if (!qry.http(sip)) return "";
|
|
||||||
return qry.receive("rand");
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SubscriberRegistry::getRandForAuthentication(bool sip, string IMSI, uint64_t *hRAND, uint64_t *lRAND)
|
|
||||||
{
|
|
||||||
string strRAND = getRandForAuthentication(sip, IMSI);
|
|
||||||
if (strRAND.length() == 0) {
|
|
||||||
*hRAND = 0;
|
|
||||||
*lRAND = 0;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
stringToUint(strRAND, hRAND, lRAND);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SubscriberRegistry::stringToUint(string strRAND, uint64_t *hRAND, uint64_t *lRAND)
|
|
||||||
{
|
|
||||||
assert(strRAND.size() == 32);
|
|
||||||
string strhRAND = strRAND.substr(0, 16);
|
|
||||||
string strlRAND = strRAND.substr(16, 16);
|
|
||||||
stringstream ssh;
|
|
||||||
ssh << hex << strhRAND;
|
|
||||||
ssh >> *hRAND;
|
|
||||||
stringstream ssl;
|
|
||||||
ssl << hex << strlRAND;
|
|
||||||
ssl >> *lRAND;
|
|
||||||
}
|
|
||||||
|
|
||||||
string SubscriberRegistry::uintToString(uint64_t h, uint64_t l)
|
|
||||||
{
|
|
||||||
ostringstream os1;
|
|
||||||
os1.width(16);
|
|
||||||
os1.fill('0');
|
|
||||||
os1 << hex << h;
|
|
||||||
ostringstream os2;
|
|
||||||
os2.width(16);
|
|
||||||
os2.fill('0');
|
|
||||||
os2 << hex << l;
|
|
||||||
ostringstream os3;
|
|
||||||
os3 << os1.str() << os2.str();
|
|
||||||
return os3.str();
|
|
||||||
}
|
|
||||||
|
|
||||||
string SubscriberRegistry::uintToString(uint32_t x)
|
|
||||||
{
|
|
||||||
ostringstream os;
|
|
||||||
os.width(8);
|
|
||||||
os.fill('0');
|
|
||||||
os << hex << x;
|
|
||||||
return os.str();
|
|
||||||
}
|
|
||||||
|
|
||||||
SubscriberRegistry::Status SubscriberRegistry::authenticate(bool sip, string IMSI, uint64_t hRAND, uint64_t lRAND, uint32_t SRES)
|
|
||||||
{
|
|
||||||
string strRAND = uintToString(hRAND, lRAND);
|
|
||||||
string strSRES = uintToString(SRES);
|
|
||||||
return authenticate(sip, IMSI, strRAND, strSRES);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
SubscriberRegistry::Status SubscriberRegistry::authenticate(bool sip, string IMSI, string rand, string sres)
|
|
||||||
{
|
|
||||||
if (IMSI.length() == 0) {
|
|
||||||
LOG(WARNING) << "SubscriberRegistry::authenticate attempting lookup of NULL IMSI";
|
|
||||||
return FAILURE;
|
|
||||||
}
|
|
||||||
LOG(INFO) << "authenticate(" << IMSI << "," << rand << "," << sres << ")";
|
|
||||||
HttpQuery qry("auth");
|
|
||||||
qry.send("imsi", IMSI);
|
|
||||||
qry.send("rand", rand);
|
|
||||||
qry.send("sres", sres);
|
|
||||||
qry.log();
|
|
||||||
if (!qry.http(sip)) return FAILURE;
|
|
||||||
const char *status = qry.receive("status");
|
|
||||||
if (strcmp(status, "SUCCESS") == 0) return SUCCESS;
|
|
||||||
if (strcmp(status, "FAILURE") == 0) return FAILURE;
|
|
||||||
// status is Kc
|
|
||||||
return SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool SubscriberRegistry::useGateway(const char* ISDN)
|
|
||||||
{
|
|
||||||
// FIXME -- Do something more general in Asterisk.
|
|
||||||
// This is a hack for Burning Man.
|
|
||||||
int cmp = strncmp(ISDN,"88351000125",11);
|
|
||||||
return cmp!=0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
SubscriberRegistry::Status SubscriberRegistry::setPrepaid(const char *IMSI, bool yes)
|
|
||||||
{
|
|
||||||
ostringstream os;
|
|
||||||
os << "update sip_buddies set prepaid = " << (yes ? 1 : 0) << " where username = " << '"' << IMSI << '"';
|
|
||||||
return sqlUpdate(os.str().c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
SubscriberRegistry::Status SubscriberRegistry::isPrepaid(const char *IMSI, bool &yes)
|
|
||||||
{
|
|
||||||
char *st = sqlQuery("prepaid", "sip_buddies", "username", IMSI);
|
|
||||||
if (!st) {
|
|
||||||
LOG(NOTICE) << "cannot get prepaid status for username " << IMSI;
|
|
||||||
return FAILURE;
|
|
||||||
}
|
|
||||||
yes = *st == '1';
|
|
||||||
free(st);
|
|
||||||
return SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
SubscriberRegistry::Status SubscriberRegistry::balanceRemaining(const char *IMSI, int &balance)
|
|
||||||
{
|
|
||||||
char *st = sqlQuery("account_balance", "sip_buddies", "username", IMSI);
|
|
||||||
if (!st) {
|
|
||||||
LOG(NOTICE) << "cannot get balance for " << IMSI;
|
|
||||||
return FAILURE;
|
|
||||||
}
|
|
||||||
balance = (int)strtol(st, (char **)NULL, 10);
|
|
||||||
free(st);
|
|
||||||
return SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
SubscriberRegistry::Status SubscriberRegistry::addMoney(const char *IMSI, int moneyToAdd)
|
|
||||||
{
|
|
||||||
ostringstream os;
|
|
||||||
os << "update sip_buddies set account_balance = account_balance + " << moneyToAdd << " where username = " << '"' << IMSI << '"';
|
|
||||||
if (sqlUpdate(os.str().c_str()) == FAILURE) {
|
|
||||||
LOG(NOTICE) << "cannot update rate for username " << IMSI;
|
|
||||||
return FAILURE;
|
|
||||||
}
|
|
||||||
return SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
int SubscriberRegistry::serviceCost(const char* service)
|
|
||||||
{
|
|
||||||
char *rateSt = sqlQuery("rate", "rates", "service", service);
|
|
||||||
if (!rateSt) {
|
|
||||||
LOG(ALERT) << "cannot get rate for service " << service;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
int rate = (int)strtol(rateSt, (char **)NULL, 10);
|
|
||||||
free(rateSt);
|
|
||||||
return rate;
|
|
||||||
}
|
|
||||||
|
|
||||||
SubscriberRegistry::Status SubscriberRegistry::serviceUnits(const char *IMSI, const char* service, int &units)
|
|
||||||
{
|
|
||||||
int balance;
|
|
||||||
Status stat = balanceRemaining(IMSI,balance);
|
|
||||||
if (stat == FAILURE) return FAILURE;
|
|
||||||
int rate = serviceCost(service);
|
|
||||||
if (rate<0) return FAILURE;
|
|
||||||
units = balance / rate;
|
|
||||||
return SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
HttpQuery::HttpQuery(const char *req)
|
|
||||||
{
|
|
||||||
sends = map<string,string>();
|
|
||||||
sends["req"] = req;
|
|
||||||
receives = map<string,string>();
|
|
||||||
}
|
|
||||||
|
|
||||||
void HttpQuery::send(const char *label, string value)
|
|
||||||
{
|
|
||||||
sends[label] = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
void HttpQuery::log()
|
|
||||||
{
|
|
||||||
ostringstream os;
|
|
||||||
bool first = true;
|
|
||||||
for (map<string,string>::iterator it = sends.begin(); it != sends.end(); it++) {
|
|
||||||
if (first) {
|
|
||||||
first = false;
|
|
||||||
} else {
|
|
||||||
os << "&";
|
|
||||||
}
|
|
||||||
os << it->first << "=" << it->second;
|
|
||||||
}
|
|
||||||
LOG(INFO) << os.str();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool HttpQuery::http(bool sip)
|
|
||||||
{
|
|
||||||
// unique temporary file names
|
|
||||||
ostringstream os1;
|
|
||||||
ostringstream os2;
|
|
||||||
os1 << "/tmp/subscriberregistry.1." << getpid();
|
|
||||||
os2 << "/tmp/subscriberregistry.2." << getpid();
|
|
||||||
string tmpFile1 = os1.str();
|
|
||||||
string tmpFile2 = os2.str();
|
|
||||||
|
|
||||||
// write the request and params to temp file
|
|
||||||
ofstream file1(tmpFile1.c_str());
|
|
||||||
if (file1.fail()) {
|
|
||||||
LOG(ERR) << "HttpQuery::http: can't write " << tmpFile1.c_str();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
bool first = true;
|
|
||||||
for (map<string,string>::iterator it = sends.begin(); it != sends.end(); it++) {
|
|
||||||
if (first) {
|
|
||||||
first = false;
|
|
||||||
} else {
|
|
||||||
file1 << "&";
|
|
||||||
}
|
|
||||||
file1 << it->first << "=" << it->second;
|
|
||||||
}
|
|
||||||
file1.close();
|
|
||||||
|
|
||||||
// call the server
|
|
||||||
string server = sip ?
|
|
||||||
gConfig.getStr("SIP.Proxy.Registration"):
|
|
||||||
gConfig.getStr("SubscriberRegistry.UpstreamServer");
|
|
||||||
if (server.length() == 0 && !sip) return false;
|
|
||||||
ostringstream os;
|
|
||||||
os << "curl -s --data-binary @" << tmpFile1.c_str() << " " << server << " > " << tmpFile2.c_str();
|
|
||||||
LOG(INFO) << os.str();
|
|
||||||
if (server == "testing") {
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
int st = system(os.str().c_str());
|
|
||||||
if (st != 0) {
|
|
||||||
LOG(ERR) << "curl call returned " << st;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// read the http return from another temp file
|
return NULL;
|
||||||
ifstream file2(tmpFile2.c_str());
|
|
||||||
if (file2.fail()) {
|
|
||||||
LOG(ERR) << "HTTPQuery::http: can't read " << tmpFile2.c_str();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
string tmp;
|
|
||||||
while (getline(file2, tmp)) {
|
|
||||||
size_t pos = tmp.find('=');
|
|
||||||
if (pos != string::npos) {
|
|
||||||
string key = tmp.substr(0, pos);
|
|
||||||
string value = tmp.substr(pos+1);
|
|
||||||
if (key == "error") {
|
|
||||||
LOG(ERR) << "HTTPQuery::http error: " << value;
|
|
||||||
file2.close();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
receives[key] = value;
|
|
||||||
} else {
|
|
||||||
file2.close();
|
|
||||||
LOG(ERR) << "HTTPQuery::http: bad server return:";
|
|
||||||
ifstream file22(tmpFile2.c_str());
|
|
||||||
while (getline(file22, tmp)) {
|
|
||||||
LOG(ERR) << tmp;
|
|
||||||
}
|
|
||||||
file22.close();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
file2.close();
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
const char *HttpQuery::receive(const char *label)
|
|
||||||
{
|
|
||||||
map<string,string>::iterator it = receives.find(label);
|
|
||||||
return it == receives.end() ? NULL : it->second.c_str();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// vim: ts=4 sw=4
|
// vim: ts=4 sw=4
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -29,8 +29,8 @@
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <Logger.h>
|
#include <Logger.h>
|
||||||
// #include <Timeval.h>
|
#include <Timeval.h>
|
||||||
// #include <Threads.h>
|
#include <Threads.h>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include "sqlite3.h"
|
#include "sqlite3.h"
|
||||||
|
@ -44,6 +44,11 @@ class SubscriberRegistry {
|
||||||
sqlite3 *mDB; ///< database connection
|
sqlite3 *mDB; ///< database connection
|
||||||
unsigned mNumSQLTries; ///< Number of times to try an sqlite command before giving up.
|
unsigned mNumSQLTries; ///< Number of times to try an sqlite command before giving up.
|
||||||
|
|
||||||
|
#ifndef SR_API_ONLY
|
||||||
|
mutable Mutex mLock; ///< control for multithreaded read/write access to the memory based sip_buddies table
|
||||||
|
Thread mSyncer; ///< thread responsible for synchronizing the memory and disk based sip_buddies tables
|
||||||
|
#endif
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
~SubscriberRegistry();
|
~SubscriberRegistry();
|
||||||
|
@ -68,6 +73,28 @@ class SubscriberRegistry {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Grab the memory based sqlite db as a table string
|
||||||
|
*/
|
||||||
|
string getResultsAsString(string query);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Grab the columns from a table
|
||||||
|
*/
|
||||||
|
vector<string> getTableColumns(string tableName);
|
||||||
|
|
||||||
|
#ifndef SR_API_ONLY
|
||||||
|
/**
|
||||||
|
Generate the SQL query which is used to sync the in-memory database to disk
|
||||||
|
to account for differences in database schemas.
|
||||||
|
*/
|
||||||
|
string generateSyncToDiskQuery();
|
||||||
|
|
||||||
|
/**
|
||||||
|
Sync the in-memory sip_buddies table to disk.
|
||||||
|
*/
|
||||||
|
bool syncMemoryDB();
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Resolve an ISDN or other numeric address to an IMSI.
|
Resolve an ISDN or other numeric address to an IMSI.
|
||||||
|
@ -102,20 +129,32 @@ class SubscriberRegistry {
|
||||||
char* getRegistrationIP(const char* IMSI);
|
char* getRegistrationIP(const char* IMSI);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Set a specific variable indexed by imsi from sip_buddies
|
Get a subscriber's property.
|
||||||
@param imsi The user's IMSI or SIP username.
|
@param imsi imsi of the subscriber
|
||||||
@param key to index into table
|
@param key name of the property
|
||||||
*/
|
*/
|
||||||
string imsiGet(string imsi, string key);
|
string imsiGet(string imsi, string key);
|
||||||
|
|
||||||
|
#ifndef SR_API_ONLY
|
||||||
/**
|
/**
|
||||||
Set a specific variable indexed by imsi_from sip_buddies
|
Set a subscriber's property.
|
||||||
@param imsi The user's IMSI or SIP username.
|
@param imsi imsi of the subscriber
|
||||||
@param key to index into table
|
@param key name of the property
|
||||||
@param value to set indexed by the key
|
@param value value of the property
|
||||||
*/
|
*/
|
||||||
bool imsiSet(string imsi, string key, string value);
|
bool imsiSet(string imsi, string key, string value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Set a subscriber's property.
|
||||||
|
@param imsi imsi of the subscriber
|
||||||
|
@param key1 name of the property
|
||||||
|
@param value1 value of the property
|
||||||
|
@param key2 name of the property
|
||||||
|
@param value2 value of the property
|
||||||
|
*/
|
||||||
|
bool imsiSet(string imsi, string key1, string value1, string key2, string value2);
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Add a new user to the SubscriberRegistry.
|
Add a new user to the SubscriberRegistry.
|
||||||
@param IMSI The user's IMSI or SIP username.
|
@param IMSI The user's IMSI or SIP username.
|
||||||
|
@ -141,99 +180,6 @@ class SubscriberRegistry {
|
||||||
char *mapCLIDGlobal(const char *local);
|
char *mapCLIDGlobal(const char *local);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
Get a 128-bit number for authentication.
|
|
||||||
@param sip sip server (true) or http
|
|
||||||
@param IMSI The user's IMSI or SIP username.
|
|
||||||
@return the 128-bit number in hex
|
|
||||||
*/
|
|
||||||
string getRandForAuthentication(bool sip, string IMSI);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
Get a 128-bit number for authentication.
|
|
||||||
@param sip sip server (true) or http
|
|
||||||
@param IMSI The user's IMSI or SIP username;
|
|
||||||
@param hRAND upper 64 bits
|
|
||||||
@param lRAND lower 64 bits
|
|
||||||
*/
|
|
||||||
bool getRandForAuthentication(bool sip, string IMSI, uint64_t *hRAND, uint64_t *lRAND);
|
|
||||||
|
|
||||||
void stringToUint(string strRAND, uint64_t *hRAND, uint64_t *lRAND);
|
|
||||||
|
|
||||||
string uintToString(uint64_t h, uint64_t l);
|
|
||||||
|
|
||||||
string uintToString(uint32_t x);
|
|
||||||
|
|
||||||
SubscriberRegistry::Status authenticate(bool sip, string IMSI, uint64_t hRAND, uint64_t lRAND, uint32_t SRES);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
Authenticate a handset.
|
|
||||||
@param sip sip server (true) or http
|
|
||||||
@param IMSI The user's IMSI or SIP username.
|
|
||||||
@param rand RAND.
|
|
||||||
@param sres SRES
|
|
||||||
@return ok or fail
|
|
||||||
*/
|
|
||||||
SubscriberRegistry::Status authenticate(bool sip, string IMSI, string rand, string sres);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool useGateway(const char* ISDN);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
Set whether a subscriber is prepaid.
|
|
||||||
@param IMSI Subscriber's IMSI
|
|
||||||
@param yes true for prepaid, false for postpaid
|
|
||||||
@return SUCCESS or FAILURE
|
|
||||||
*/
|
|
||||||
Status setPrepaid(const char *IMSI, bool yes);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
Is a subscriber postpaid?
|
|
||||||
@param IMSI Subscriber's IMSI
|
|
||||||
@param yes set to true if subscriber is postpaid, false if prepaid
|
|
||||||
@return SUCCESS or FAILURE
|
|
||||||
*/
|
|
||||||
Status isPrepaid(const char *IMSI, bool &yes);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
Get the balance remaining in a subscriber's account.
|
|
||||||
@param IMSI Subscriber's IMSI
|
|
||||||
@param balance current account balance
|
|
||||||
@return SUCCESS or FAILURE
|
|
||||||
*/
|
|
||||||
Status balanceRemaining(const char *IMSI, int &balance);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
Atomic operation to add to the account balance
|
|
||||||
@param IMSI subscriber's IMSI
|
|
||||||
@param moneyToAdd money to add (negative to subtract)
|
|
||||||
@return SUCCESS or FAILURE
|
|
||||||
*/
|
|
||||||
Status addMoney(const char *IMSI, int moneyToAdd);
|
|
||||||
|
|
||||||
/**
|
|
||||||
Return the number of "units" of a particular transcation type available in the user's account.
|
|
||||||
@param IMSI subscriber's IMSI
|
|
||||||
@param service the service type
|
|
||||||
@param units number of units of this service type remaining
|
|
||||||
@return SUCCESS or FAILURE
|
|
||||||
*/
|
|
||||||
Status serviceUnits(const char *IMSI, const char* service, int &units);
|
|
||||||
|
|
||||||
/**
|
|
||||||
Return the cost per unit of a specific service type.
|
|
||||||
*/
|
|
||||||
int serviceCost(const char* service);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Update the RRLP location for user
|
Update the RRLP location for user
|
||||||
@param name IMSI to be updated
|
@param name IMSI to be updated
|
||||||
|
@ -257,15 +203,6 @@ class SubscriberRegistry {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
Run sql statments over http.
|
|
||||||
@param stmt The sql statements.
|
|
||||||
@param resultptr Set this to point to the result of executing the statements.
|
|
||||||
*/
|
|
||||||
Status sqlHttp(const char *stmt, char **resultptr);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Run an sql query (select unknownColumn from table where knownColumn = knownValue).
|
Run an sql query (select unknownColumn from table where knownColumn = knownValue).
|
||||||
@param unknownColumn The column whose value you want.
|
@param unknownColumn The column whose value you want.
|
||||||
|
@ -284,82 +221,10 @@ class SubscriberRegistry {
|
||||||
Status sqlUpdate(const char *stmt);
|
Status sqlUpdate(const char *stmt);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/** Class that SubscriberRegistry uses to setup an http query, run it, and get the results. */
|
|
||||||
class HttpQuery {
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
Constructor.
|
|
||||||
@param req The type of http query (sql, (get a)rand(om number) auth(enticate), etc).
|
|
||||||
*/
|
|
||||||
HttpQuery(const char *req);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
Specify a parameter to send in the http query.
|
|
||||||
@param label The label or name for the parameter.
|
|
||||||
@param value The value of the parameter.
|
|
||||||
*/
|
|
||||||
void send(const char *label, string value);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
Log the query.
|
|
||||||
*/
|
|
||||||
void log();
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
This runs the http query.
|
|
||||||
@param sip Whether to call the sip server as opposed to the http server.
|
|
||||||
*/
|
|
||||||
bool http(bool sip);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
Get result from the http query.
|
|
||||||
@param label The label or name of the parameter whose value you want.
|
|
||||||
*/
|
|
||||||
const char *receive(const char *label);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/** stores the parameters to send. */
|
|
||||||
map<string,string> sends;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/** stores the return parameters. */
|
|
||||||
map<string,string> receives;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** Periodically triggers SubscriberRegistry::syncMemoryDB(). */
|
||||||
|
void* subscriberRegistrySyncer(void*);
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -0,0 +1,58 @@
|
||||||
|
#
|
||||||
|
# Copyright 2013 Range Networks, Inc.
|
||||||
|
#
|
||||||
|
# This software is distributed under the terms of the GNU Public License.
|
||||||
|
# See the COPYING file in the main directory for details.
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
|
||||||
|
include $(top_srcdir)/Makefile.common
|
||||||
|
|
||||||
|
DESTDIR :=
|
||||||
|
|
||||||
|
ourlibs = \
|
||||||
|
$(GLOBALS_LA) \
|
||||||
|
$(COMMON_LA) \
|
||||||
|
$(SQLITE_LA) \
|
||||||
|
$(NODEMANAGER_LA)
|
||||||
|
|
||||||
|
bin_PROGRAMS = sipauthserve comp128
|
||||||
|
|
||||||
|
sipauthserve_SOURCES = sipauthserve.cpp ../servershare.cpp ../SubscriberRegistry.cpp \
|
||||||
|
../NodeManager/JSONDB/JSONDB.cpp
|
||||||
|
sipauthserve_CPPFLAGS = $(STD_DEFINES_AND_INCLUDES)
|
||||||
|
sipauthserve_LDADD = $(ourlibs) -losipparser2 -losip2
|
||||||
|
|
||||||
|
comp128_SOURCES = comp128.c
|
||||||
|
comp128_CPPFLAGS = $(STD_DEFINES_AND_INCLUDES)
|
||||||
|
comp128_LDADD = $(ourlibs)
|
||||||
|
|
||||||
|
EXTRA_DIST = \
|
||||||
|
subscriberRegistry.example.sql \
|
||||||
|
sipauthserve.conf
|
||||||
|
|
||||||
|
# Populating comp128 in both locations for backwards compat
|
||||||
|
install: sipauthserve comp128
|
||||||
|
mkdir -p "$(DESTDIR)/OpenBTS/"
|
||||||
|
install comp128 "$(DESTDIR)/OpenBTS/"
|
||||||
|
install sipauthserve "$(DESTDIR)/OpenBTS/"
|
||||||
|
mkdir -p "$(DESTDIR)/usr/local/bin/"
|
||||||
|
install comp128 "$(DESTDIR)/usr/local/bin/"
|
||||||
|
install syslogextractor "$(DESTDIR)/usr/local/bin/"
|
||||||
|
install hexmapper "$(DESTDIR)/usr/local/bin/"
|
||||||
|
mkdir -p "$(DESTDIR)/etc/init/"
|
||||||
|
install sipauthserve.conf "$(DESTDIR)/etc/init/"
|
||||||
|
mkdir -p "$(DESTDIR)/etc/OpenBTS/"
|
||||||
|
install subscriberRegistry.example.sql "$(DESTDIR)/etc/OpenBTS/"
|
|
@ -0,0 +1,10 @@
|
||||||
|
# sipauthserve - Range Networks SIP Authorization Server
|
||||||
|
#
|
||||||
|
# This service runs sipauthserve from the point the system is
|
||||||
|
# started until it is shut down again.
|
||||||
|
|
||||||
|
start on stopped rc RUNLEVEL=[2345]
|
||||||
|
stop on runlevel [!2345]
|
||||||
|
|
||||||
|
respawn
|
||||||
|
exec /OpenBTS/sipauthserve
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2011 Kestrel Signal Processing, Inc.
|
* Copyright 2011 Kestrel Signal Processing, Inc.
|
||||||
* Copyright 2011 Range Networks, Inc.
|
* Copyright 2011, 2014 Range Networks, Inc.
|
||||||
*
|
*
|
||||||
* This software is distributed under the terms of the GNU Affero Public License.
|
* This software is distributed under the terms of the GNU Affero Public License.
|
||||||
* See the COPYING file in the main directory for details.
|
* See the COPYING file in the main directory for details.
|
||||||
|
@ -44,7 +44,9 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include <Logger.h>
|
#include <Logger.h>
|
||||||
#include <Configuration.h>
|
#include <Globals.h>
|
||||||
|
#include <NodeManager.h>
|
||||||
|
#include <JSONDB.h>
|
||||||
#include "servershare.h"
|
#include "servershare.h"
|
||||||
#include "SubscriberRegistry.h"
|
#include "SubscriberRegistry.h"
|
||||||
|
|
||||||
|
@ -58,6 +60,29 @@ int my_udp_port;
|
||||||
// just using this for the database access
|
// just using this for the database access
|
||||||
SubscriberRegistry gSubscriberRegistry;
|
SubscriberRegistry gSubscriberRegistry;
|
||||||
|
|
||||||
|
/** The remote node manager. */
|
||||||
|
NodeManager gNodeManager;
|
||||||
|
|
||||||
|
/** The JSON<->DB interface. */
|
||||||
|
JSONDB gJSONDB;
|
||||||
|
|
||||||
|
/** Application specific NodeManager logic for handling requests. */
|
||||||
|
JsonBox::Object nmHandler(JsonBox::Object& request)
|
||||||
|
{
|
||||||
|
JsonBox::Object response;
|
||||||
|
std::string command = request["command"].getString();
|
||||||
|
std::string action = request["action"].getString();
|
||||||
|
|
||||||
|
if (command.compare("subscribers") == 0) {
|
||||||
|
request["table"] = JsonBox::Value("subscribers");
|
||||||
|
response = gJSONDB.query(request);
|
||||||
|
} else {
|
||||||
|
response["code"] = JsonBox::Value(501);
|
||||||
|
}
|
||||||
|
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
void prettyPrint(const char *label, osip_message_t *sip)
|
void prettyPrint(const char *label, osip_message_t *sip)
|
||||||
{
|
{
|
||||||
char *dest=NULL;
|
char *dest=NULL;
|
||||||
|
@ -73,14 +98,13 @@ void prettyPrint(const char *label, osip_message_t *sip)
|
||||||
|
|
||||||
string imsiFromSip(osip_message_t *sip)
|
string imsiFromSip(osip_message_t *sip)
|
||||||
{
|
{
|
||||||
int i;
|
|
||||||
char *dest;
|
char *dest;
|
||||||
osip_uri_t *fromUri = osip_from_get_url(sip->from);
|
osip_uri_t *fromUri = osip_from_get_url(sip->from);
|
||||||
if (!fromUri) {
|
if (!fromUri) {
|
||||||
LOG(ERR) << "osip_from_get_url problem";
|
LOG(ERR) << "osip_from_get_url problem";
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
i = osip_uri_to_str(fromUri, &dest);
|
osip_uri_to_str(fromUri, &dest);
|
||||||
string imsi = dest;
|
string imsi = dest;
|
||||||
osip_free(dest);
|
osip_free(dest);
|
||||||
return imsi;
|
return imsi;
|
||||||
|
@ -88,14 +112,13 @@ string imsiFromSip(osip_message_t *sip)
|
||||||
|
|
||||||
string imsiToSip(osip_message_t *sip)
|
string imsiToSip(osip_message_t *sip)
|
||||||
{
|
{
|
||||||
int i;
|
|
||||||
char *dest;
|
char *dest;
|
||||||
osip_uri_t *toUri = osip_to_get_url(sip->to);
|
osip_uri_t *toUri = osip_to_get_url(sip->to);
|
||||||
if (!toUri) {
|
if (!toUri) {
|
||||||
LOG(ERR) << "osip_to_get_url problem";
|
LOG(ERR) << "osip_to_get_url problem";
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
i = osip_uri_to_str(toUri, &dest);
|
osip_uri_to_str(toUri, &dest);
|
||||||
string imsi = dest;
|
string imsi = dest;
|
||||||
osip_free(dest);
|
osip_free(dest);
|
||||||
return imsi;
|
return imsi;
|
||||||
|
@ -104,7 +127,7 @@ string imsiToSip(osip_message_t *sip)
|
||||||
// is imsi in the database?
|
// is imsi in the database?
|
||||||
bool imsiFound(string imsi)
|
bool imsiFound(string imsi)
|
||||||
{
|
{
|
||||||
string x = imsiGet(imsi, "id");
|
string x = gSubscriberRegistry.imsiGet(imsi, "id");
|
||||||
return x.length() != 0;
|
return x.length() != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -180,7 +203,7 @@ char *processBuffer(char *buffer)
|
||||||
osip_message_set_status_code (response, 200);
|
osip_message_set_status_code (response, 200);
|
||||||
osip_message_set_reason_phrase (response, osip_strdup("OK"));
|
osip_message_set_reason_phrase (response, osip_strdup("OK"));
|
||||||
LOG(INFO) << "success, registering for IP address " << remote_host;
|
LOG(INFO) << "success, registering for IP address " << remote_host;
|
||||||
imsiSet(imsi,"ipaddr", remote_host, "port", remote_port);
|
gSubscriberRegistry.imsiSet(imsi,"ipaddr", remote_host, "port", remote_port);
|
||||||
} else {
|
} else {
|
||||||
// look for rand and sres in Authorization header (assume imsi same as in from)
|
// look for rand and sres in Authorization header (assume imsi same as in from)
|
||||||
string randx;
|
string randx;
|
||||||
|
@ -238,9 +261,19 @@ char *processBuffer(char *buffer)
|
||||||
i = osip_list_add (&response->authentication_infos, auth, -1);
|
i = osip_list_add (&response->authentication_infos, auth, -1);
|
||||||
if (i < 0) LOG(ERR) << "problem adding authentication_infos";
|
if (i < 0) LOG(ERR) << "problem adding authentication_infos";
|
||||||
}
|
}
|
||||||
|
// (pat 9-2013) Add the caller id.
|
||||||
|
static string calleridstr("callerid");
|
||||||
|
string callid = gSubscriberRegistry.imsiGet(imsi,calleridstr);
|
||||||
|
if (callid.size()) {
|
||||||
|
char buf[120];
|
||||||
|
// Per RFC3966 the telephone numbers should begin with "+" only if it is globally unique throughout the world.
|
||||||
|
// We should not add the "+" here, it should be in the database if appropriate.
|
||||||
|
snprintf(buf,120,"<tel:%s>",callid.c_str());
|
||||||
|
osip_message_set_header(response,"P-Associated-URI",buf);
|
||||||
|
}
|
||||||
// And register it.
|
// And register it.
|
||||||
LOG(INFO) << "success, registering for IP address " << remote_host;
|
LOG(INFO) << "success, registering for IP address " << remote_host;
|
||||||
imsiSet(imsi,"ipaddr", remote_host, "port", remote_port);
|
gSubscriberRegistry.imsiSet(imsi,"ipaddr", remote_host, "port", remote_port);
|
||||||
} else {
|
} else {
|
||||||
// sres does not match rand => 401 Unauthorized
|
// sres does not match rand => 401 Unauthorized
|
||||||
osip_message_set_status_code (response, 401);
|
osip_message_set_status_code (response, 401);
|
||||||
|
@ -269,6 +302,24 @@ char *processBuffer(char *buffer)
|
||||||
int
|
int
|
||||||
main(int argc, char **argv)
|
main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
|
// TODO: Properly parse and handle any arguments
|
||||||
|
if (argc > 1) {
|
||||||
|
for (int argi = 0; argi < argc; argi++) {
|
||||||
|
if (!strcmp(argv[argi], "--version") ||
|
||||||
|
!strcmp(argv[argi], "-v")) {
|
||||||
|
cout << gVersionString << endl;
|
||||||
|
}
|
||||||
|
if (!strcmp(argv[argi], "--gensql")) {
|
||||||
|
cout << gConfig.getDefaultSQL(string(argv[0]), gVersionString) << endl;
|
||||||
|
}
|
||||||
|
if (!strcmp(argv[argi], "--gentex")) {
|
||||||
|
cout << gConfig.getTeX(string(argv[0]), gVersionString) << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
sockaddr_in si_me;
|
sockaddr_in si_me;
|
||||||
sockaddr_in si_other;
|
sockaddr_in si_other;
|
||||||
int aSocket;
|
int aSocket;
|
||||||
|
@ -278,13 +329,15 @@ main(int argc, char **argv)
|
||||||
srand ( time(NULL) + (int)getpid() );
|
srand ( time(NULL) + (int)getpid() );
|
||||||
my_udp_port = gConfig.getNum("SubscriberRegistry.Port");
|
my_udp_port = gConfig.getNum("SubscriberRegistry.Port");
|
||||||
gSubscriberRegistry.init();
|
gSubscriberRegistry.init();
|
||||||
|
gNodeManager.setAppLogicHandler(&nmHandler);
|
||||||
|
gNodeManager.start(45064);
|
||||||
|
|
||||||
// init osip lib
|
// init osip lib
|
||||||
osip_t *osip;
|
osip_t *osip;
|
||||||
int i=osip_init(&osip);
|
int i=osip_init(&osip);
|
||||||
if (i!=0) {
|
if (i!=0) {
|
||||||
LOG(ALERT) << "cannot init sip lib";
|
LOG(ALERT) << "cannot init sip lib";
|
||||||
return NULL;
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((aSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) {
|
if ((aSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) {
|
|
@ -0,0 +1,20 @@
|
||||||
|
--
|
||||||
|
-- This file was generated using: ./sipauthserve --gensql
|
||||||
|
-- binary version: release 4.0TRUNK built Nov 20 2013 rev6847M
|
||||||
|
--
|
||||||
|
-- Future changes should not be put in this file directly but
|
||||||
|
-- rather in the program's ConfigurationKey schema.
|
||||||
|
--
|
||||||
|
PRAGMA foreign_keys=OFF;
|
||||||
|
BEGIN TRANSACTION;
|
||||||
|
CREATE TABLE IF NOT EXISTS CONFIG ( KEYSTRING TEXT UNIQUE NOT NULL, VALUESTRING TEXT, STATIC INTEGER DEFAULT 0, OPTIONAL INTEGER DEFAULT 0, COMMENTS TEXT DEFAULT '');
|
||||||
|
INSERT OR IGNORE INTO "CONFIG" VALUES('Control.NumSQLTries','3',0,0,'Number of times to retry SQL queries before declaring a database access failure.');
|
||||||
|
INSERT OR IGNORE INTO "CONFIG" VALUES('Log.Alarms.Max','20',0,0,'Maximum number of alarms to remember inside the application.');
|
||||||
|
INSERT OR IGNORE INTO "CONFIG" VALUES('Log.File','',0,0,'Path to use for textfile based logging. By default, this feature is disabled. To enable, specify an absolute path to the file you wish to use, eg: /tmp/my-debug.log. To disable again, execute "unconfig Log.File".');
|
||||||
|
INSERT OR IGNORE INTO "CONFIG" VALUES('Log.Level','NOTICE',0,0,'Default logging level when no other level is defined for a file.');
|
||||||
|
INSERT OR IGNORE INTO "CONFIG" VALUES('SubscriberRegistry.A3A8','/OpenBTS/comp128',0,0,'Path to the program that implements the A3/A8 algorithm.');
|
||||||
|
INSERT OR IGNORE INTO "CONFIG" VALUES('SubscriberRegistry.Port','5064',0,0,'Port used by the SIP Authentication Server. NOTE: In some older releases (pre-2.8.1) this is called SIP.myPort.');
|
||||||
|
INSERT OR IGNORE INTO "CONFIG" VALUES('SubscriberRegistry.db','/var/lib/asterisk/sqlite3dir/sqlite3.db',0,0,'The location of the sqlite3 database holding the subscriber registry.');
|
||||||
|
COMMIT;
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
105
config.h
105
config.h
|
@ -1,105 +0,0 @@
|
||||||
//
|
|
||||||
// Sorry, SubscriberRegistry didn't need fancy make setup before the library sync, and I wasn't in the mood to create it for the sync, so I just copied the openbts config.h here.
|
|
||||||
//
|
|
||||||
/* config.h. Generated from config.h.in by configure. */
|
|
||||||
/* config.h.in. Generated from configure.ac by autoheader. */
|
|
||||||
|
|
||||||
/* Define if building universal (internal helper macro) */
|
|
||||||
/* #undef AC_APPLE_UNIVERSAL_BUILD */
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <byteswap.h> header file. */
|
|
||||||
#define HAVE_BYTESWAP_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <dlfcn.h> header file. */
|
|
||||||
#define HAVE_DLFCN_H 1
|
|
||||||
|
|
||||||
/* Define if libc implements gethostbyname2_r */
|
|
||||||
#define HAVE_GETHOSTBYNAME2_R 1
|
|
||||||
|
|
||||||
/* Define if libc implements gethostbyname_r */
|
|
||||||
#define HAVE_GETHOSTBYNAME_R 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
|
||||||
#define HAVE_INTTYPES_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <memory.h> header file. */
|
|
||||||
#define HAVE_MEMORY_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <stdint.h> header file. */
|
|
||||||
#define HAVE_STDINT_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
|
||||||
#define HAVE_STDLIB_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <strings.h> header file. */
|
|
||||||
#define HAVE_STRINGS_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <string.h> header file. */
|
|
||||||
#define HAVE_STRING_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/stat.h> header file. */
|
|
||||||
#define HAVE_SYS_STAT_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
|
||||||
#define HAVE_SYS_TYPES_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <unistd.h> header file. */
|
|
||||||
#define HAVE_UNISTD_H 1
|
|
||||||
|
|
||||||
/* Define to the sub-directory in which libtool stores uninstalled libraries.
|
|
||||||
*/
|
|
||||||
#define LT_OBJDIR ".libs/"
|
|
||||||
|
|
||||||
/* Name of package */
|
|
||||||
#define PACKAGE "openbts"
|
|
||||||
|
|
||||||
/* Define to the address where bug reports for this package should be sent. */
|
|
||||||
#define PACKAGE_BUGREPORT ""
|
|
||||||
|
|
||||||
/* Define to the full name of this package. */
|
|
||||||
#define PACKAGE_NAME "openbts"
|
|
||||||
|
|
||||||
/* Define to the full name and version of this package. */
|
|
||||||
#define PACKAGE_STRING "openbts 3.0TRUNK"
|
|
||||||
|
|
||||||
/* Define to the one symbol short name of this package. */
|
|
||||||
#define PACKAGE_TARNAME "openbts"
|
|
||||||
|
|
||||||
/* Define to the home page for this package. */
|
|
||||||
#define PACKAGE_URL ""
|
|
||||||
|
|
||||||
/* Define to the version of this package. */
|
|
||||||
#define PACKAGE_VERSION "3.0TRUNK"
|
|
||||||
|
|
||||||
/* Define to 1 if you have the ANSI C header files. */
|
|
||||||
#define STDC_HEADERS 1
|
|
||||||
|
|
||||||
/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
|
|
||||||
#define TIME_WITH_SYS_TIME 1
|
|
||||||
|
|
||||||
/* Version number of package */
|
|
||||||
#define VERSION "3.0TRUNK"
|
|
||||||
|
|
||||||
/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
|
|
||||||
significant byte first (like Motorola and SPARC, unlike Intel). */
|
|
||||||
#if defined AC_APPLE_UNIVERSAL_BUILD
|
|
||||||
# if defined __BIG_ENDIAN__
|
|
||||||
# define WORDS_BIGENDIAN 1
|
|
||||||
# endif
|
|
||||||
#else
|
|
||||||
# ifndef WORDS_BIGENDIAN
|
|
||||||
/* # undef WORDS_BIGENDIAN */
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Define to empty if `const' does not conform to ANSI C. */
|
|
||||||
/* #undef const */
|
|
||||||
|
|
||||||
/* Define to `__inline__' or `__inline' if that's what the C compiler
|
|
||||||
calls it, or to nothing if 'inline' is not supported under any name. */
|
|
||||||
#ifndef __cplusplus
|
|
||||||
/* #undef inline */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Define to `unsigned int' if <sys/types.h> does not define. */
|
|
||||||
/* #undef size_t */
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
#
|
||||||
|
# Copyright 2008 Free Software Foundation, Inc.
|
||||||
|
#
|
||||||
|
# This software is distributed under the terms of the GNU Public License.
|
||||||
|
# See the COPYING file in the main directory for details.
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
|
||||||
|
include $(top_srcdir)/Makefile.common
|
||||||
|
|
||||||
|
# Install m4 macros in this directory
|
||||||
|
m4datadir = $(datadir)/aclocal
|
||||||
|
|
||||||
|
# List your m4 macros here
|
||||||
|
m4macros = \
|
||||||
|
pkg.m4
|
||||||
|
|
||||||
|
EXTRA_DIST = $(m4macros)
|
|
@ -0,0 +1,188 @@
|
||||||
|
# pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*-
|
||||||
|
#
|
||||||
|
# Copyright © 2004 Scott James Remnant <scott@netsplit.com>.
|
||||||
|
# Copyright © 2008 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 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.
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
# PKG_PROG_PKG_CONFIG([MIN-VERSION])
|
||||||
|
# ----------------------------------
|
||||||
|
AC_DEFUN([PKG_PROG_PKG_CONFIG],
|
||||||
|
[m4_pattern_forbid([^_?PKG_[A-Z_]+$])
|
||||||
|
m4_pattern_allow([^PKG_CONFIG(_PATH)?$])
|
||||||
|
AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility])dnl
|
||||||
|
if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then
|
||||||
|
AC_PATH_TOOL([PKG_CONFIG], [pkg-config])
|
||||||
|
fi
|
||||||
|
if test -n "$PKG_CONFIG"; then
|
||||||
|
_pkg_min_version=m4_default([$1], [0.18])
|
||||||
|
AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version])
|
||||||
|
if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then
|
||||||
|
AC_MSG_RESULT([yes])
|
||||||
|
else
|
||||||
|
AC_MSG_RESULT([no])
|
||||||
|
PKG_CONFIG=""
|
||||||
|
fi
|
||||||
|
|
||||||
|
fi[]dnl
|
||||||
|
])# PKG_PROG_PKG_CONFIG
|
||||||
|
|
||||||
|
# PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
|
||||||
|
#
|
||||||
|
# Check to see whether a particular set of modules exists. Similar
|
||||||
|
# to PKG_CHECK_MODULES(), but does not set variables or print errors.
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# Similar to PKG_CHECK_MODULES, make sure that the first instance of
|
||||||
|
# this or PKG_CHECK_MODULES is called, or make sure to call
|
||||||
|
# PKG_CHECK_EXISTS manually
|
||||||
|
# --------------------------------------------------------------
|
||||||
|
AC_DEFUN([PKG_CHECK_EXISTS],
|
||||||
|
[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
|
||||||
|
if test -n "$PKG_CONFIG" && \
|
||||||
|
AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then
|
||||||
|
m4_ifval([$2], [$2], [:])
|
||||||
|
m4_ifvaln([$3], [else
|
||||||
|
$3])dnl
|
||||||
|
fi])
|
||||||
|
|
||||||
|
|
||||||
|
# _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES])
|
||||||
|
# ---------------------------------------------
|
||||||
|
m4_define([_PKG_CONFIG],
|
||||||
|
[if test -n "$PKG_CONFIG"; then
|
||||||
|
if test -n "$$1"; then
|
||||||
|
pkg_cv_[]$1="$$1"
|
||||||
|
else
|
||||||
|
PKG_CHECK_EXISTS([$3],
|
||||||
|
[pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null`],
|
||||||
|
[pkg_failed=yes])
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
pkg_failed=untried
|
||||||
|
fi[]dnl
|
||||||
|
])# _PKG_CONFIG
|
||||||
|
|
||||||
|
# _PKG_SHORT_ERRORS_SUPPORTED
|
||||||
|
# -----------------------------
|
||||||
|
AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED],
|
||||||
|
[AC_REQUIRE([PKG_PROG_PKG_CONFIG])
|
||||||
|
if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
|
||||||
|
_pkg_short_errors_supported=yes
|
||||||
|
else
|
||||||
|
_pkg_short_errors_supported=no
|
||||||
|
fi[]dnl
|
||||||
|
])# _PKG_SHORT_ERRORS_SUPPORTED
|
||||||
|
|
||||||
|
|
||||||
|
# PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND],
|
||||||
|
# [ACTION-IF-NOT-FOUND])
|
||||||
|
#
|
||||||
|
# E.g.,
|
||||||
|
# PKG_CHECK_MODULES(GSTUFF, gtk+-2.0 >= 1.3 glib = 1.3.4, action-if, action-not)
|
||||||
|
# defines:
|
||||||
|
#
|
||||||
|
# GSTUFF_LIBS
|
||||||
|
# GSTUFF_CFLAGS
|
||||||
|
# GSTUFF_INCLUDEDIR
|
||||||
|
# GSTUFF_CPPFLAGS # the -I, -D and -U's out of CFLAGS
|
||||||
|
#
|
||||||
|
# see pkg-config man page also defines GSTUFF_PKG_ERRORS on error
|
||||||
|
#
|
||||||
|
# Note that if there is a possibility the first call to
|
||||||
|
# PKG_CHECK_MODULES might not happen, you should be sure to include an
|
||||||
|
# explicit call to PKG_PROG_PKG_CONFIG in your configure.ac
|
||||||
|
#
|
||||||
|
# --------------------------------------------------------------
|
||||||
|
AC_DEFUN([PKG_CHECK_MODULES],
|
||||||
|
[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
|
||||||
|
AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl
|
||||||
|
AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl
|
||||||
|
AC_ARG_VAR([$1][_INCLUDEDIR], [includedir for $1, overriding pkg-config])dnl
|
||||||
|
|
||||||
|
pkg_failed=no
|
||||||
|
AC_MSG_CHECKING([for $1])
|
||||||
|
|
||||||
|
_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2])
|
||||||
|
|
||||||
|
if test x$cross_compiling = xyes
|
||||||
|
then
|
||||||
|
_PKG_CONFIG([$1][_LIBS], [libs-only-l --static], [$2])
|
||||||
|
else
|
||||||
|
_PKG_CONFIG([$1][_LIBS], [libs --static], [$2])
|
||||||
|
fi
|
||||||
|
|
||||||
|
_PKG_CONFIG([$1][_INCLUDEDIR], [variable=includedir], [$2])
|
||||||
|
|
||||||
|
|
||||||
|
m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS
|
||||||
|
and $1[]_LIBS to avoid the need to call pkg-config.
|
||||||
|
See the pkg-config man page for more details.])
|
||||||
|
|
||||||
|
if test $pkg_failed = yes; then
|
||||||
|
_PKG_SHORT_ERRORS_SUPPORTED
|
||||||
|
if test $_pkg_short_errors_supported = yes; then
|
||||||
|
$1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "$2"`
|
||||||
|
else
|
||||||
|
$1[]_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "$2"`
|
||||||
|
fi
|
||||||
|
# Put the nasty error message in config.log where it belongs
|
||||||
|
echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD
|
||||||
|
|
||||||
|
ifelse([$4], , [AC_MSG_ERROR(dnl
|
||||||
|
[Package requirements ($2) were not met:
|
||||||
|
|
||||||
|
$$1_PKG_ERRORS
|
||||||
|
|
||||||
|
Consider adjusting the PKG_CONFIG_PATH environment variable if you
|
||||||
|
installed software in a non-standard prefix.
|
||||||
|
|
||||||
|
_PKG_TEXT
|
||||||
|
])],
|
||||||
|
[AC_MSG_RESULT([no])
|
||||||
|
$4])
|
||||||
|
elif test $pkg_failed = untried; then
|
||||||
|
ifelse([$4], , [AC_MSG_FAILURE(dnl
|
||||||
|
[The pkg-config script could not be found or is too old. Make sure it
|
||||||
|
is in your PATH or set the PKG_CONFIG environment variable to the full
|
||||||
|
path to pkg-config.
|
||||||
|
|
||||||
|
_PKG_TEXT
|
||||||
|
|
||||||
|
To get pkg-config, see <http://pkg-config.freedesktop.org/>.])],
|
||||||
|
[$4])
|
||||||
|
else
|
||||||
|
$1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS
|
||||||
|
$1[]_LIBS=$pkg_cv_[]$1[]_LIBS
|
||||||
|
$1[]_INCLUDEDIR=$pkg_cv_[]$1[]_INCLUDEDIR
|
||||||
|
|
||||||
|
$1[]_CPPFLAGS=""
|
||||||
|
for flag in $$1[]_CFLAGS; do
|
||||||
|
case $flag in
|
||||||
|
-I* | -D* | -U*) $1[]_CPPFLAGS="$$1[]_CPPFLAGS $flag" ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
pkg_cv_[]$1[]_CPPFLAGS=$$1[]_CPPFLAGS
|
||||||
|
AC_SUBST($1[]_CPPFLAGS)
|
||||||
|
|
||||||
|
AC_MSG_RESULT([yes])
|
||||||
|
ifelse([$3], , :, [$3])
|
||||||
|
fi[]dnl
|
||||||
|
])# PKG_CHECK_MODULES
|
|
@ -0,0 +1,87 @@
|
||||||
|
dnl
|
||||||
|
dnl Copyright 2008, 2009, 2010 Free Software Foundation, Inc.
|
||||||
|
dnl
|
||||||
|
dnl This software is distributed under the terms of the GNU Public License.
|
||||||
|
dnl See the COPYING file in the main directory for details.
|
||||||
|
dnl
|
||||||
|
dnl This program is free software: you can redistribute it and/or modify
|
||||||
|
dnl it under the terms of the GNU General Public License as published by
|
||||||
|
dnl the Free Software Foundation, either version 3 of the License, or
|
||||||
|
dnl (at your option) any later version.
|
||||||
|
dnl
|
||||||
|
dnl This program is distributed in the hope that it will be useful,
|
||||||
|
dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
dnl GNU General Public License for more details.
|
||||||
|
dnl
|
||||||
|
dnl You should have received a copy of the GNU General Public License
|
||||||
|
dnl along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
dnl
|
||||||
|
|
||||||
|
AC_INIT(subscriberregistry,4.0TRUNK)
|
||||||
|
AC_PREREQ(2.57)
|
||||||
|
AC_CONFIG_SRCDIR([config/Makefile.am])
|
||||||
|
AC_CONFIG_AUX_DIR([.])
|
||||||
|
AM_CONFIG_HEADER(config.h)
|
||||||
|
|
||||||
|
AC_CANONICAL_BUILD
|
||||||
|
AC_CANONICAL_HOST
|
||||||
|
AC_CANONICAL_TARGET
|
||||||
|
|
||||||
|
AM_INIT_AUTOMAKE
|
||||||
|
|
||||||
|
AM_PROG_AS
|
||||||
|
AC_PROG_CXX
|
||||||
|
AC_PROG_LN_S
|
||||||
|
AC_PROG_MAKE_SET
|
||||||
|
AC_PROG_INSTALL
|
||||||
|
AC_PATH_PROG([RM_PROG], [rm])
|
||||||
|
|
||||||
|
AC_LIBTOOL_WIN32_DLL
|
||||||
|
AC_ENABLE_SHARED dnl do build shared libraries
|
||||||
|
AC_DISABLE_STATIC dnl don't build static libraries
|
||||||
|
AC_PROG_LIBTOOL
|
||||||
|
|
||||||
|
dnl Checks for header files.
|
||||||
|
AC_HEADER_STDC
|
||||||
|
dnl This is required for GnuRadio includes to understand endianess correctly:
|
||||||
|
AC_CHECK_HEADERS([byteswap.h])
|
||||||
|
|
||||||
|
dnl Checks for typedefs, structures, and compiler characteristics.
|
||||||
|
AC_C_CONST
|
||||||
|
AC_C_INLINE
|
||||||
|
AC_TYPE_SIZE_T
|
||||||
|
AC_HEADER_TIME
|
||||||
|
AC_C_BIGENDIAN
|
||||||
|
|
||||||
|
dnl Check for libzmq
|
||||||
|
if test ! -r "/usr/include/zmq.h" -a ! -r "/usr/local/include/zmq.h"; then
|
||||||
|
AC_MSG_ERROR([/usr/local/include/zmq.h not found. Install the range-libzmq package or manually build and install with $ sudo ./NodeManager/install_libzmq.sh])
|
||||||
|
fi
|
||||||
|
if test ! -r "/usr/include/zmq.hpp" -a ! -r "/usr/local/include/zmq.hpp"; then
|
||||||
|
AC_MSG_ERROR([/usr/local/include/zmq.hpp not found. Install the range-libzmq package or manually build and install with $ sudo ./NodeManager/install_libzmq.sh])
|
||||||
|
fi
|
||||||
|
AC_CHECK_LIB(zmq, zmq_init, ,[AC_MSG_ERROR([Cannot link with -lzmq. Install the range-libzmq package or manually build and install with $ sudo ./NodeManager/install_libzmq.sh])])
|
||||||
|
AC_MSG_CHECKING([whether libzmq installation works])
|
||||||
|
AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <zmq.h>],
|
||||||
|
[zmq_init(1);])
|
||||||
|
],
|
||||||
|
[AC_MSG_RESULT([yes])],
|
||||||
|
[AC_MSG_ERROR([no. Install the range-libzmq package or manually build and install with $ sudo ./NodeManager/install_libzmq.sh])])
|
||||||
|
|
||||||
|
# Check for glibc-specific network functions
|
||||||
|
AC_CHECK_FUNC(gethostbyname_r, [AC_DEFINE(HAVE_GETHOSTBYNAME_R, 1, Define if libc implements gethostbyname_r)])
|
||||||
|
AC_CHECK_FUNC(gethostbyname2_r, [AC_DEFINE(HAVE_GETHOSTBYNAME2_R, 1, Define if libc implements gethostbyname2_r)])
|
||||||
|
|
||||||
|
dnl Output files
|
||||||
|
AC_CONFIG_FILES([\
|
||||||
|
Makefile \
|
||||||
|
apps/Makefile \
|
||||||
|
config/Makefile \
|
||||||
|
CommonLibs/Makefile \
|
||||||
|
Globals/Makefile \
|
||||||
|
NodeManager/Makefile \
|
||||||
|
sqlite3/Makefile \
|
||||||
|
])
|
||||||
|
|
||||||
|
AC_OUTPUT
|
|
@ -1,12 +1,5 @@
|
||||||
sipauthserve-public (3.2) UNRELEASED; urgency=low
|
sipauthserve (4.0) unstable; urgency=low
|
||||||
|
|
||||||
* Non-maintainer upload.
|
|
||||||
* Public release
|
|
||||||
|
|
||||||
-- Kurtis <kheimerl@rangenetworks.com> Tue, 30 Jul 2013 23:01:28 -0700
|
|
||||||
|
|
||||||
sipauthserve-public (3.2) UNRELEASED; urgency=low
|
|
||||||
|
|
||||||
* Test
|
* Test
|
||||||
|
|
||||||
-- Donald C. Kirker <donald.kirker@rangenetworks.com> Mon, 22 Apr 2013 00:11:00 -0700
|
-- Donald C. Kirker <donald.kirker@rangenetworks.com> Mon, 22 Apr 2013 00:11:00 -0700
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
1
|
|
|
@ -1,19 +1,16 @@
|
||||||
Source: sipauthserve-public
|
Source: sipauthserve
|
||||||
Provides: sipauthserve
|
|
||||||
Section: comm
|
Section: comm
|
||||||
Priority: optional
|
Priority: optional
|
||||||
Maintainer: Range Networks, Inc. <info@rangenetworks.com>
|
Maintainer: Range Networks, Inc. <info@rangenetworks.com>
|
||||||
Homepage: http://www.rangenetworks.com/
|
Homepage: http://www.rangenetworks.com/
|
||||||
Build-Depends: build-essential, debhelper (>= 7), libosip2-dev, pkg-config, autoconf, libsqlite3-dev (>= 3.7)
|
Build-Depends: build-essential, debhelper (>= 7), libosip2-dev, pkg-config, autoconf, libtool
|
||||||
Standards-Version: 3.7.3
|
Standards-Version: 3.7.3
|
||||||
|
|
||||||
Package: sipauthserve-public
|
Package: sipauthserve
|
||||||
Provides: sipauthserve
|
|
||||||
Version: TRUNK
|
|
||||||
Section: comm
|
Section: comm
|
||||||
Priority: optional
|
Priority: optional
|
||||||
Architecture: any
|
Architecture: i386
|
||||||
Essential: no
|
Essential: no
|
||||||
Depends: sqlite, sqlite3 (>= 3.7), libosip2-4, libglib2.0-0, libgl1-mesa-glx, libc6, libasound2, pkg-config, libpcre3, gawk, screen
|
Depends: sqlite3, libosip2-4, libc6-i686, pkg-config, range-libzmq
|
||||||
Description: OpenBTS Public software.
|
Description: Range Networks - SIP Authorization Server
|
||||||
|
|
||||||
|
|
|
@ -19,37 +19,37 @@ set -e
|
||||||
|
|
||||||
configure()
|
configure()
|
||||||
{
|
{
|
||||||
DB_LOC=/etc/OpenBTS/sipauthserve.db
|
DATE=$(date --rfc-3339='date')
|
||||||
DATE=$(date +'%Y-%m-%d.%H:%M:%S')
|
CONFIG_BACKUP=/etc/OpenBTS/OpenBTS.dump-$DATE
|
||||||
CONFIG_BACKUP=$DB_LOC.dump-$DATE
|
|
||||||
|
|
||||||
if [ ! -e $CONFIG_BACKUP ]; then
|
if [ ! -e $CONFIG_BACKUP ]; then
|
||||||
sqlite3 $DB_LOC ".dump" > $CONFIG_BACKUP
|
sqlite3 /etc/OpenBTS/OpenBTS.db ".dump" > $CONFIG_BACKUP
|
||||||
fi
|
fi
|
||||||
|
|
||||||
sqlite3 $DB_LOC ".read /etc/OpenBTS/subscriberRegistry.example.sql" > /dev/null 2>&1
|
sqlite3 /etc/OpenBTS/OpenBTS.db ".read /etc/OpenBTS/subscriberRegistry.example.sql" > /dev/null 2>&1
|
||||||
|
|
||||||
SR_DIR=/var/lib/asterisk/sqlite3dir
|
if [ ! -d /var/lib/asterisk/sqlite3dir ]; then
|
||||||
SRPATH=$SR_DIR/sqlite3.db
|
mkdir -p /var/lib/asterisk/sqlite3dir
|
||||||
|
fi
|
||||||
|
|
||||||
|
SRPATH=/var/lib/asterisk/sqlite3dir/sqlite3.db
|
||||||
|
|
||||||
|
DATE=$(date --rfc-3339='date')
|
||||||
SR_CONFIG_BACKUP=$SRPATH.dump-$DATE
|
SR_CONFIG_BACKUP=$SRPATH.dump-$DATE
|
||||||
|
|
||||||
if [ ! -d $SR_DIR ]; then
|
|
||||||
mkdir -p $SR_DIR
|
|
||||||
fi
|
|
||||||
chown -R root:www-data $SR_DIR
|
|
||||||
chmod 775 $SR_DIR
|
|
||||||
|
|
||||||
if [[ -e $SRPATH && "`sqlite3 $SRPATH "PRAGMA table_info(sip_buddies)"`" != "" ]]; then
|
if [[ -e $SRPATH && "`sqlite3 $SRPATH "PRAGMA table_info(sip_buddies)" || true`" != "" ]]; then
|
||||||
if [ ! -e $SR_CONFIG_BACKUP ]; then
|
if [ ! -e $SR_CONFIG_BACKUP ]; then
|
||||||
sqlite3 $SRPATH ".dump" > $SR_CONFIG_BACKUP
|
sqlite3 $SRPATH ".dump" > $SR_CONFIG_BACKUP
|
||||||
fi
|
fi
|
||||||
|
|
||||||
HASPREPAID=`sqlite3 $SRPATH "PRAGMA table_info(sip_buddies)" | grep prepaid`
|
HASPREPAID=`sqlite3 $SRPATH "PRAGMA table_info(sip_buddies)" | grep prepaid || true`
|
||||||
if [ "$HASPREPAID" = "" ]; then
|
if [ "$HASPREPAID" = "" ]; then
|
||||||
sqlite3 $SRPATH "alter table sip_buddies add prepaid int(1) DEFAULT 0 not null"
|
sqlite3 $SRPATH "alter table sip_buddies add prepaid int(1) DEFAULT 0 not null"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
HASBALANCE=`sqlite3 $SRPATH "PRAGMA table_info(sip_buddies)" | grep account_balance`
|
HASBALANCE=`sqlite3 $SRPATH "PRAGMA table_info(sip_buddies)" | grep account_balance || true`
|
||||||
if [ "$HASBALANCE" = "" ]; then
|
if [ "$HASBALANCE" = "" ]; then
|
||||||
sqlite3 $SRPATH "alter table sip_buddies add column account_balance int(9) default 0"
|
sqlite3 $SRPATH "alter table sip_buddies add column account_balance int(9) default 0"
|
||||||
fi
|
fi
|
||||||
|
@ -64,8 +64,10 @@ fi
|
||||||
|
|
||||||
# set up permissions for webui, temporary fix until ui is replumbed to use json
|
# set up permissions for webui, temporary fix until ui is replumbed to use json
|
||||||
# directory permissions
|
# directory permissions
|
||||||
if [ -e $SRPATH ]; then
|
chown -R root:www-data /var/lib/asterisk/sqlite3dir
|
||||||
chmod 664 $SR_DIR/sqlite3*
|
chmod 775 /var/lib/asterisk/sqlite3dir/
|
||||||
|
if [ -e /var/lib/asterisk/sqlite3dir/sqlite3.db ]; then
|
||||||
|
chmod 664 /var/lib/asterisk/sqlite3dir/sqlite3*
|
||||||
fi
|
fi
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,16 +16,14 @@ set -e
|
||||||
# for details, see http://www.debian.org/doc/debian-policy/ or
|
# for details, see http://www.debian.org/doc/debian-policy/ or
|
||||||
# the debian-policy package
|
# the debian-policy package
|
||||||
|
|
||||||
APP=sipauthserve
|
# remove()
|
||||||
|
# {
|
||||||
remove()
|
# killall runloop.sipauthserve.sh &>/dev/null
|
||||||
{
|
# }
|
||||||
killall $APP &>/dev/null
|
|
||||||
}
|
|
||||||
|
|
||||||
case "$1" in
|
case "$1" in
|
||||||
remove|upgrade|deconfigure)
|
remove|upgrade|deconfigure)
|
||||||
remove
|
# remove
|
||||||
;;
|
;;
|
||||||
|
|
||||||
failed-upgrade)
|
failed-upgrade)
|
||||||
|
|
|
@ -20,11 +20,13 @@ export DH_ALWAYS_EXCLUDE=.svn:.git
|
||||||
export DH_OPTIONS
|
export DH_OPTIONS
|
||||||
|
|
||||||
configure:
|
configure:
|
||||||
|
./autogen.sh
|
||||||
|
|
||||||
config: configure-stamp
|
config: configure-stamp
|
||||||
configure-stamp: configure
|
configure-stamp: configure
|
||||||
dh_testdir
|
dh_testdir
|
||||||
# Add here commands to configure the package.
|
# Add here commands to configure the package.
|
||||||
|
./configure $(confflags)
|
||||||
touch configure-stamp
|
touch configure-stamp
|
||||||
|
|
||||||
#Architecture
|
#Architecture
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
|
|
||||||
# A script to restart and just keep sipauthserve running.
|
|
||||||
while true; do killall sipauthserve; sleep 2; ./sipauthserve; done
|
|
193
servershare.cpp
193
servershare.cpp
|
@ -29,6 +29,7 @@
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <Configuration.h>
|
#include <Configuration.h>
|
||||||
|
#include <Utils.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "servershare.h"
|
#include "servershare.h"
|
||||||
|
@ -51,18 +52,6 @@ ConfigurationKeyMap getConfigurationKeys()
|
||||||
ConfigurationKeyMap map;
|
ConfigurationKeyMap map;
|
||||||
ConfigurationKey *tmp;
|
ConfigurationKey *tmp;
|
||||||
|
|
||||||
tmp = new ConfigurationKey("SIP.Proxy.Registration","127.0.0.1:5064",
|
|
||||||
"",
|
|
||||||
ConfigurationKey::CUSTOMERWARN,
|
|
||||||
ConfigurationKey::IPANDPORT,
|
|
||||||
"",
|
|
||||||
false,
|
|
||||||
"The IP host and port of the proxy to be used for registration and authentication. "
|
|
||||||
"This should normally be the subscriber registry SIP interface, not Asterisk."
|
|
||||||
);
|
|
||||||
map[tmp->getName()] = *tmp;
|
|
||||||
delete tmp;
|
|
||||||
|
|
||||||
tmp = new ConfigurationKey("SubscriberRegistry.A3A8","/OpenBTS/comp128",
|
tmp = new ConfigurationKey("SubscriberRegistry.A3A8","/OpenBTS/comp128",
|
||||||
"",
|
"",
|
||||||
ConfigurationKey::CUSTOMERWARN,
|
ConfigurationKey::CUSTOMERWARN,
|
||||||
|
@ -85,28 +74,6 @@ ConfigurationKeyMap getConfigurationKeys()
|
||||||
map[tmp->getName()] = *tmp;
|
map[tmp->getName()] = *tmp;
|
||||||
delete tmp;
|
delete tmp;
|
||||||
|
|
||||||
tmp = new ConfigurationKey("SubscriberRegistry.Manager.Title","Subscriber Registry",
|
|
||||||
"",
|
|
||||||
ConfigurationKey::CUSTOMER,
|
|
||||||
ConfigurationKey::STRING,
|
|
||||||
"^[[:print:]]+$",
|
|
||||||
false,
|
|
||||||
"Title text to be displayed on the subscriber registry manager."
|
|
||||||
);
|
|
||||||
map[tmp->getName()] = *tmp;
|
|
||||||
delete tmp;
|
|
||||||
|
|
||||||
tmp = new ConfigurationKey("SubscriberRegistry.Manager.VisibleColumns","name username type context host",
|
|
||||||
"",
|
|
||||||
ConfigurationKey::CUSTOMERTUNE,
|
|
||||||
ConfigurationKey::STRING,
|
|
||||||
"^(name){0,1} (username){0,1} (type){0,1} (context){0,1} (host){0,1}$",
|
|
||||||
false,
|
|
||||||
"A space separated list of columns to display in the subscriber registry manager."
|
|
||||||
);
|
|
||||||
map[tmp->getName()] = *tmp;
|
|
||||||
delete tmp;
|
|
||||||
|
|
||||||
tmp = new ConfigurationKey("SubscriberRegistry.Port","5064",
|
tmp = new ConfigurationKey("SubscriberRegistry.Port","5064",
|
||||||
"",
|
"",
|
||||||
ConfigurationKey::CUSTOMERWARN,
|
ConfigurationKey::CUSTOMERWARN,
|
||||||
|
@ -118,58 +85,9 @@ ConfigurationKeyMap getConfigurationKeys()
|
||||||
map[tmp->getName()] = *tmp;
|
map[tmp->getName()] = *tmp;
|
||||||
delete tmp;
|
delete tmp;
|
||||||
|
|
||||||
tmp = new ConfigurationKey("SubscriberRegistry.UpstreamServer","",
|
|
||||||
"",
|
|
||||||
ConfigurationKey::CUSTOMERWARN,
|
|
||||||
ConfigurationKey::STRING_OPT,// audited
|
|
||||||
"",
|
|
||||||
false,
|
|
||||||
"URL of the subscriber registry HTTP interface on the upstream server. "
|
|
||||||
"By default, this feature is disabled. "
|
|
||||||
"To enable, specify a server URL eg: http://localhost/cgi/subreg.cgi. "
|
|
||||||
"To disable again, execute \"unconfig SubscriberRegistry.UpstreamServer\"."
|
|
||||||
);
|
|
||||||
map[tmp->getName()] = *tmp;
|
|
||||||
delete tmp;
|
|
||||||
|
|
||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
string imsiGet(string imsi, string key)
|
|
||||||
{
|
|
||||||
string name = imsi.substr(0,4) == "IMSI" ? imsi : "IMSI" + imsi;
|
|
||||||
char *value;
|
|
||||||
if (!sqlite3_single_lookup(gSubscriberRegistry.db(), "sip_buddies", "username", name.c_str(), key.c_str(), value)) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
if (!value) { return ""; }
|
|
||||||
string retValue = value;
|
|
||||||
free(value);
|
|
||||||
return retValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
void imsiSet(string imsi, string key, string value)
|
|
||||||
{
|
|
||||||
string name = imsi.substr(0,4) == "IMSI" ? imsi : "IMSI" + imsi;
|
|
||||||
ostringstream os2;
|
|
||||||
os2 << "update sip_buddies set " << key << " = \"" << value << "\" where username = \"" << name << "\"";
|
|
||||||
if (!sqlite3_command(gSubscriberRegistry.db(), os2.str().c_str())) {
|
|
||||||
LOG(ERR) << "sqlite3_command problem";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void imsiSet(string imsi, string key1, string value1, string key2, string value2)
|
|
||||||
{
|
|
||||||
string name = imsi.substr(0,4) == "IMSI" ? imsi : "IMSI" + imsi;
|
|
||||||
ostringstream os2;
|
|
||||||
os2 << "update sip_buddies set " << key1 << " = \"" << value1 << "\"," << key2 << " = \"" << value2 << "\" where username = \"" << name << "\"";
|
|
||||||
if (!sqlite3_command(gSubscriberRegistry.db(), os2.str().c_str())) {
|
|
||||||
LOG(ERR) << "sqlite3_command problem";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
string soGenerateIt()
|
string soGenerateIt()
|
||||||
{
|
{
|
||||||
ostringstream os;
|
ostringstream os;
|
||||||
|
@ -180,20 +98,18 @@ string soGenerateIt()
|
||||||
return os.str();
|
return os.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// generate a 128' random number
|
// generate a 128' random number
|
||||||
string generateRand(string imsi)
|
string generateRand(string imsi)
|
||||||
{
|
{
|
||||||
string ki = imsiGet(imsi, "ki");
|
string ki = gSubscriberRegistry.imsiGet(imsi, "ki");
|
||||||
string ret;
|
string ret;
|
||||||
if (ki.length() != 0) {
|
if (ki.length() != 0) {
|
||||||
LOG(INFO) << "ki is known";
|
LOG(INFO) << "ki is known";
|
||||||
// generate and return rand (clear any cached rand or sres)
|
// generate and return rand (clear any cached rand or sres)
|
||||||
imsiSet(imsi, "rand", "", "sres", "");
|
gSubscriberRegistry.imsiSet(imsi, "rand", "", "sres", "");
|
||||||
ret = soGenerateIt();
|
ret = soGenerateIt();
|
||||||
} else {
|
} else {
|
||||||
string wRand = imsiGet(imsi, "rand");
|
string wRand = gSubscriberRegistry.imsiGet(imsi, "rand");
|
||||||
if (wRand.length() != 0) {
|
if (wRand.length() != 0) {
|
||||||
LOG(INFO) << "ki is unknown, rand is cached";
|
LOG(INFO) << "ki is unknown, rand is cached";
|
||||||
// return cached rand
|
// return cached rand
|
||||||
|
@ -202,7 +118,7 @@ string generateRand(string imsi)
|
||||||
LOG(INFO) << "ki is unknown, rand is not cached";
|
LOG(INFO) << "ki is unknown, rand is not cached";
|
||||||
// generate rand, cache rand, clear sres, and return rand
|
// generate rand, cache rand, clear sres, and return rand
|
||||||
wRand = soGenerateIt();
|
wRand = soGenerateIt();
|
||||||
imsiSet(imsi, "rand", wRand, "sres", "");
|
gSubscriberRegistry.imsiSet(imsi, "rand", wRand, "sres", "");
|
||||||
ret = wRand;
|
ret = wRand;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -246,8 +162,8 @@ bool randEqual(string a, string b)
|
||||||
if (a.empty() || b.empty())
|
if (a.empty() || b.empty())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
gSubscriberRegistry.stringToUint(a, &rand1h, &rand1l);
|
Utils::stringToUint(a, &rand1h, &rand1l);
|
||||||
gSubscriberRegistry.stringToUint(b, &rand2h, &rand2l);
|
Utils::stringToUint(b, &rand2h, &rand2l);
|
||||||
|
|
||||||
LOG(DEBUG) << "rand1h = " << rand1h << ", rand1l = " << rand1l;
|
LOG(DEBUG) << "rand1h = " << rand1h << ", rand1l = " << rand1l;
|
||||||
LOG(DEBUG) << "rand2h = " << rand2h << ", rand2l = " << rand2l;
|
LOG(DEBUG) << "rand2h = " << rand2h << ", rand2l = " << rand2l;
|
||||||
|
@ -260,40 +176,31 @@ bool randEqual(string a, string b)
|
||||||
// may cache sres and rand
|
// may cache sres and rand
|
||||||
bool authenticate(string imsi, string randx, string sres, string *kc)
|
bool authenticate(string imsi, string randx, string sres, string *kc)
|
||||||
{
|
{
|
||||||
string ki = imsiGet(imsi, "ki");
|
string ki = gSubscriberRegistry.imsiGet(imsi, "ki");
|
||||||
bool ret;
|
bool ret;
|
||||||
if (ki.length() == 0) {
|
if (ki.length() == 0) {
|
||||||
// Ki is unknown
|
// Ki is unknown
|
||||||
string upstream_server = gConfig.getStr("SubscriberRegistry.UpstreamServer");
|
string sres2 = gSubscriberRegistry.imsiGet(imsi, "sres");
|
||||||
if (upstream_server.length()) {
|
if (sres2.length() == 0) {
|
||||||
LOG(INFO) << "ki unknown, upstream server";
|
LOG(INFO) << "ki unknown, no upstream server, sres not cached";
|
||||||
// there's an upstream server for authentication.
|
// first time - cache sres and rand so next time
|
||||||
// TODO - call the upstream server
|
// correct cell phone will calc same sres from same rand
|
||||||
ret = false;
|
gSubscriberRegistry.imsiSet(imsi, "sres", sres, "rand", randx);
|
||||||
|
ret = true;
|
||||||
} else {
|
} else {
|
||||||
// there's no upstream server for authentication. fake it.
|
LOG(INFO) << "ki unknown, no upstream server, sres cached";
|
||||||
string sres2 = imsiGet(imsi, "sres");
|
// check against cached values of rand and sres
|
||||||
if (sres2.length() == 0) {
|
string rand2 = gSubscriberRegistry.imsiGet(imsi, "rand");
|
||||||
LOG(INFO) << "ki unknown, no upstream server, sres not cached";
|
// TODO - on success, compute and return kc
|
||||||
// first time - cache sres and rand so next time
|
LOG(DEBUG) << "comparing " << sres << " to " << sres2 << " and " << randx << " to " << rand2;
|
||||||
// correct cell phone will calc same sres from same rand
|
ret = sresEqual(sres, sres2) && randEqual(randx, rand2);
|
||||||
imsiSet(imsi, "sres", sres, "rand", randx);
|
|
||||||
ret = true;
|
|
||||||
} else {
|
|
||||||
LOG(INFO) << "ki unknown, no upstream server, sres cached";
|
|
||||||
// check against cached values of rand and sres
|
|
||||||
string rand2 = imsiGet(imsi, "rand");
|
|
||||||
// TODO - on success, compute and return kc
|
|
||||||
LOG(DEBUG) << "comparing " << sres << " to " << sres2 << " and " << randx << " to " << rand2;
|
|
||||||
ret = sresEqual(sres, sres2) && randEqual(randx, rand2);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
LOG(INFO) << "ki known";
|
LOG(INFO) << "ki known";
|
||||||
// Ki is known, so do normal authentication
|
// Ki is known, so do normal authentication
|
||||||
ostringstream os;
|
ostringstream os;
|
||||||
// per user value from subscriber registry
|
// per user value from subscriber registry
|
||||||
string a3a8 = imsiGet(imsi, "a3_a8");
|
string a3a8 = gSubscriberRegistry.imsiGet(imsi, "a3_a8");
|
||||||
if (a3a8.length() == 0) {
|
if (a3a8.length() == 0) {
|
||||||
// config value is default
|
// config value is default
|
||||||
a3a8 = gConfig.getStr("SubscriberRegistry.A3A8");
|
a3a8 = gConfig.getStr("SubscriberRegistry.A3A8");
|
||||||
|
@ -328,62 +235,6 @@ bool authenticate(string imsi, string randx, string sres, string *kc)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void decodeQuery(map<string,string> &args)
|
|
||||||
{
|
|
||||||
string query;
|
|
||||||
// this works for GET or POST.
|
|
||||||
// get the request method
|
|
||||||
char *g = getenv("REQUEST_METHOD");
|
|
||||||
string method = g ? g : "";
|
|
||||||
LOG(INFO) << "REQUEST_METHOD = " << g;
|
|
||||||
// if POST, then read from stdin the number of bytes specified in CONTENT_LENGTH, and that's the query
|
|
||||||
if (method == "POST") {
|
|
||||||
int lth = atoi(getenv("CONTENT_LENGTH"));
|
|
||||||
LOG(INFO) << "CONTENT_LENGTH = " << lth;
|
|
||||||
char *buf = new char[lth+1];
|
|
||||||
cin.get(buf, lth+1);
|
|
||||||
int nread = cin.gcount();
|
|
||||||
if (nread != lth) {
|
|
||||||
LOG(ERR) << "content length changed to " << nread;
|
|
||||||
lth = nread;
|
|
||||||
}
|
|
||||||
query = string(buf, lth);
|
|
||||||
LOG(INFO) << "QUERY = " << query;
|
|
||||||
delete[] buf;
|
|
||||||
// if GET, then the query is in the environment variable QUERY_STRING
|
|
||||||
} else if (method == "GET") {
|
|
||||||
char *q = getenv("QUERY_STRING");
|
|
||||||
query = q ? q : "";
|
|
||||||
LOG(INFO) << "QUERY_STRING = " << q;
|
|
||||||
}
|
|
||||||
if (query.length() != 0) {
|
|
||||||
// fields of http request are separated with "&"
|
|
||||||
vector<string> fields;
|
|
||||||
split('&', query, &fields);
|
|
||||||
vector<string>::iterator it;
|
|
||||||
for (it = fields.begin(); it != fields.end(); it++) {
|
|
||||||
string field = *it;
|
|
||||||
size_t p = field.find('=');
|
|
||||||
string key = field.substr(0, p);
|
|
||||||
string value = field.substr(p+1);
|
|
||||||
p = 0;
|
|
||||||
while (1) {
|
|
||||||
size_t q = value.find('%', p);
|
|
||||||
if (q == string::npos) break;
|
|
||||||
string hex = value.substr(q+1, 2);
|
|
||||||
char s[2];
|
|
||||||
strcpy(s, "x");
|
|
||||||
int i;
|
|
||||||
sscanf(hex.c_str(), "%x", &i);
|
|
||||||
s[0] = i;
|
|
||||||
string hexx = s;
|
|
||||||
value.replace(q, 3, hexx);
|
|
||||||
}
|
|
||||||
args[key] = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
string join(string separator, vector<string> &strings)
|
string join(string separator, vector<string> &strings)
|
||||||
{
|
{
|
||||||
string result("");
|
string result("");
|
||||||
|
|
|
@ -34,31 +34,6 @@ using namespace std;
|
||||||
*/
|
*/
|
||||||
ConfigurationKeyMap getConfigurationKeys();
|
ConfigurationKeyMap getConfigurationKeys();
|
||||||
|
|
||||||
/**
|
|
||||||
Get a subscriber's property.
|
|
||||||
@param imsi imsi of the subscriber
|
|
||||||
@param key name of the property
|
|
||||||
*/
|
|
||||||
string imsiGet(string imsi, string key);
|
|
||||||
|
|
||||||
/**
|
|
||||||
Set a subscriber's property.
|
|
||||||
@param imsi imsi of the subscriber
|
|
||||||
@param key name of the property
|
|
||||||
@param value value of the property
|
|
||||||
*/
|
|
||||||
void imsiSet(string imsi, string key, string value);
|
|
||||||
|
|
||||||
/**
|
|
||||||
Set a subscriber's property.
|
|
||||||
@param imsi imsi of the subscriber
|
|
||||||
@param key1 name of the property
|
|
||||||
@param value1 value of the property
|
|
||||||
@param key2 name of the property
|
|
||||||
@param value2 value of the property
|
|
||||||
*/
|
|
||||||
void imsiSet(string imsi, string key1, string value1, string key2, string value2);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Generate a 128-bit random number.
|
Generate a 128-bit random number.
|
||||||
@param imsi imsi of subscriber the random number is for
|
@param imsi imsi of subscriber the random number is for
|
||||||
|
@ -73,12 +48,6 @@ string generateRand(string imsi);
|
||||||
*/
|
*/
|
||||||
bool authenticate(string imsi, string rand, string sres, string *kc);
|
bool authenticate(string imsi, string rand, string sres, string *kc);
|
||||||
|
|
||||||
/**
|
|
||||||
Decode the html query.
|
|
||||||
@param args mapping of query key->value pairs.
|
|
||||||
*/
|
|
||||||
void decodeQuery(map<string,string> &args);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Join the strings in strings, separated by separator
|
Join the strings in strings, separated by separator
|
||||||
@param separator the separator
|
@param separator the separator
|
||||||
|
|
2
sqlite3
2
sqlite3
|
@ -1 +1 @@
|
||||||
Subproject commit 3d0dbe8e7a819585cac5064beabe9b22f8d47235
|
Subproject commit effc8fe4744285c07e3710ab97231537a27b7997
|
307
srmanager.cpp
307
srmanager.cpp
|
@ -1,307 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2011 Kestrel Signal Processing, Inc.
|
|
||||||
* Copyright 2011 Range Networks, Inc.
|
|
||||||
*
|
|
||||||
* This software is distributed under the terms of the GNU Affero Public License.
|
|
||||||
* See the COPYING file in the main directory for details.
|
|
||||||
*
|
|
||||||
* This use of this software may be subject to additional restrictions.
|
|
||||||
* See the LEGAL file in the main directory for details.
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU Affero General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU Affero General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
#include <sstream>
|
|
||||||
#include <map>
|
|
||||||
#include <vector>
|
|
||||||
#include <string>
|
|
||||||
#include <sqlite3.h>
|
|
||||||
#include <time.h>
|
|
||||||
#include "Configuration.h"
|
|
||||||
#include "Logger.h"
|
|
||||||
#include <string.h>
|
|
||||||
#include "servershare.h"
|
|
||||||
#include "SubscriberRegistry.h"
|
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
ConfigurationTable gConfig("/etc/OpenBTS/OpenBTS.db", "srmanager", getConfigurationKeys());
|
|
||||||
Log dummy("srmanager",gConfig.getStr("Log.Level").c_str(),LOG_LOCAL7);
|
|
||||||
map<string,string> gArgs;
|
|
||||||
string gDatabase;
|
|
||||||
string gVisibleSipColumns;
|
|
||||||
string gUrl;
|
|
||||||
string gTitle;
|
|
||||||
string gVisibleExtColumns = "exten dial";
|
|
||||||
|
|
||||||
// just using this for the database access
|
|
||||||
SubscriberRegistry gSubscriberRegistry;
|
|
||||||
|
|
||||||
|
|
||||||
#define NO_BUTTON 0
|
|
||||||
#define UPDATE_BUTTON 1
|
|
||||||
#define ADD_BUTTON 2
|
|
||||||
#define DELETE_BUTTON 4
|
|
||||||
|
|
||||||
// may need some way to add/update a NULL field
|
|
||||||
void tableRow(vector<string> &names, vector<string> &values, int buttons, string id)
|
|
||||||
{
|
|
||||||
cout << "<form name=\"input\" action=\"" << gUrl << "\" method=\"post\">\n";
|
|
||||||
for (size_t i = 0; i < names.size(); i++) {
|
|
||||||
string name = names[i];
|
|
||||||
string value = values.size() == 0 ? "" : values[i];
|
|
||||||
cout << "<input type=\"text\" name=\"" << name << "\" value=\"" << value << "\" />\n";
|
|
||||||
}
|
|
||||||
cout << "<input type=\"hidden\" name=\"id\" value=\"" << id << "\" />\n";
|
|
||||||
if (buttons & UPDATE_BUTTON) {
|
|
||||||
cout << "<input type=\"submit\" name=\"what\" value=\"Update\" />\n";
|
|
||||||
}
|
|
||||||
if (buttons & ADD_BUTTON) {
|
|
||||||
cout << "<input type=\"submit\" name=\"what\" value=\"Add\" />\n";
|
|
||||||
}
|
|
||||||
if (buttons & DELETE_BUTTON) {
|
|
||||||
cout << "<input type=\"submit\" name=\"what\" value=\"Delete\" />\n";
|
|
||||||
}
|
|
||||||
cout << "</form>\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
// make the header a fake form to get the same widths
|
|
||||||
void initTable(vector<string> &cols)
|
|
||||||
{
|
|
||||||
tableRow(cols, cols, NO_BUTTON, "0");
|
|
||||||
}
|
|
||||||
|
|
||||||
void table(const char *tableName, vector<string> &cols, bool addButtonP, const char *note)
|
|
||||||
{
|
|
||||||
cout << "<h4>" << gDatabase << "." << tableName << " " << note << "</h4>\n";
|
|
||||||
initTable(cols);
|
|
||||||
ostringstream os;
|
|
||||||
os << "select id," << join(",", cols) << " from " << tableName;
|
|
||||||
sqlite3_stmt *stmt;
|
|
||||||
if (sqlite3_prepare_statement(gSubscriberRegistry.db(), &stmt,os.str().c_str())) {
|
|
||||||
LOG(ERR) << "sqlite3_prepare_statement problem - statement: " << os.str();
|
|
||||||
LOG(ERR) << " " << sqlite3_errmsg(gSubscriberRegistry.db());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
int src = sqlite3_run_query(gSubscriberRegistry.db(), stmt);
|
|
||||||
while (src == SQLITE_ROW) {
|
|
||||||
vector<string> values;
|
|
||||||
const char *id = (const char*)sqlite3_column_text(stmt, 0);
|
|
||||||
for (int i = 1; i <= (int)cols.size(); i++) {
|
|
||||||
const char *value = (const char*)sqlite3_column_text(stmt, i);
|
|
||||||
values.push_back(value ? value : "(null)");
|
|
||||||
}
|
|
||||||
tableRow(cols, values, UPDATE_BUTTON | DELETE_BUTTON, id);
|
|
||||||
src = sqlite3_run_query(gSubscriberRegistry.db(), stmt);
|
|
||||||
}
|
|
||||||
sqlite3_finalize(stmt);
|
|
||||||
if (addButtonP) {
|
|
||||||
vector<string> dummy;
|
|
||||||
tableRow(cols, dummy, ADD_BUTTON, "0");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void getFields(vector<string> *fields, vector<bool> *isSet)
|
|
||||||
{
|
|
||||||
vector<string> vsc;
|
|
||||||
split(' ', gVisibleSipColumns, &vsc);
|
|
||||||
sqlite3_stmt *stmt;
|
|
||||||
const char *cmd = "pragma table_info(sip_buddies)";
|
|
||||||
if (sqlite3_prepare_statement(gSubscriberRegistry.db(), &stmt, cmd)) {
|
|
||||||
LOG(ERR) << "sqlite3_prepare_statement problem - statement: " << cmd;
|
|
||||||
LOG(ERR) << " " << sqlite3_errmsg(gSubscriberRegistry.db());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
int src = sqlite3_run_query(gSubscriberRegistry.db(), stmt);
|
|
||||||
while (src == SQLITE_ROW) {
|
|
||||||
string field = (char*)sqlite3_column_text(stmt, 1);
|
|
||||||
fields->push_back(field);
|
|
||||||
isSet->push_back(find(vsc.begin(), vsc.end(), field) != vsc.end());
|
|
||||||
src = sqlite3_run_query(gSubscriberRegistry.db(), stmt);
|
|
||||||
}
|
|
||||||
sqlite3_finalize(stmt);
|
|
||||||
}
|
|
||||||
|
|
||||||
void mainTables()
|
|
||||||
{
|
|
||||||
cout << "<form name=\"provision\" action=\"" << gUrl << "\" method=\"post\">\n";
|
|
||||||
cout << "Phone Number = ";
|
|
||||||
cout << "<input type=\"text\" name=\"phonenumber\" value=\"\" />\n";
|
|
||||||
cout << "IMSI = ";
|
|
||||||
cout << "<input type=\"text\" name=\"imsi\" value=\"\" />\n";
|
|
||||||
cout << "<input type=\"submit\" name=\"what\" value=\"Provision\" />\n";
|
|
||||||
cout << "</form>\n";
|
|
||||||
cout << "<br><hr><br>\n";
|
|
||||||
|
|
||||||
vector<string> vsc;
|
|
||||||
split(' ', gVisibleSipColumns, &vsc);
|
|
||||||
table("sip_buddies", vsc, false, "(scroll down to change which fields of sip_buddies are visible)");
|
|
||||||
cout << "<hr>";
|
|
||||||
vector<string> vec;
|
|
||||||
split(' ', gVisibleExtColumns, &vec);
|
|
||||||
table("dialdata_table", vec, true, "");
|
|
||||||
|
|
||||||
cout << "<br><hr><br>\n";
|
|
||||||
cout << "<FORM METHOD=\"LINK\" ACTION=\"" << gUrl << "\"> <INPUT TYPE=\"submit\" VALUE=\"Refresh\"> </FORM>\n";
|
|
||||||
|
|
||||||
cout << "<br><hr><br>\n";
|
|
||||||
cout << "<h4>Selected fields are included in sip_buddies table (submit button at bottom)</h4>\n";
|
|
||||||
cout << "<form method=\"post\" action=\"" << gUrl << "\">\n";
|
|
||||||
vector<string> fields;
|
|
||||||
vector<bool> isSet;
|
|
||||||
getFields(&fields, &isSet);
|
|
||||||
for (int i = 0; i < (int)fields.size(); i++) {
|
|
||||||
string field = fields[i];
|
|
||||||
string checked = isSet[i] ? "checked" : "";
|
|
||||||
cout << "<input type=\"checkbox\" name=\"" << field << "\" value=\"" << field << "\"" << checked << " /> " << field << "<br />\n";
|
|
||||||
}
|
|
||||||
cout << "<br><INPUT TYPE=SUBMIT name=\"what\" VALUE=\"Submit\">\n";
|
|
||||||
cout << "</form>\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
string nullCheck(string s)
|
|
||||||
{
|
|
||||||
if (s == "(null)") {
|
|
||||||
return "NULL";
|
|
||||||
} else {
|
|
||||||
return "\"" + s + "\"";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void doCmd(string cmd)
|
|
||||||
{
|
|
||||||
string table;
|
|
||||||
vector<string> cols;
|
|
||||||
if (gArgs.find("dial") == gArgs.end()) {
|
|
||||||
table = "sip_buddies";
|
|
||||||
split(' ', gVisibleSipColumns, &cols);
|
|
||||||
} else {
|
|
||||||
table = "dialdata_table";
|
|
||||||
split(' ', gVisibleExtColumns, &cols);
|
|
||||||
}
|
|
||||||
string id = gArgs["id"];
|
|
||||||
ostringstream os;
|
|
||||||
if (cmd == "add") {
|
|
||||||
string names = join(",", cols);
|
|
||||||
vector<string> values0;
|
|
||||||
vector<string>::iterator it;
|
|
||||||
for (it = cols.begin(); it != cols.end(); it++) {
|
|
||||||
values0.push_back(nullCheck(gArgs[*it]));
|
|
||||||
}
|
|
||||||
string values = join(",", values0);
|
|
||||||
os << "insert into " << table << " (" << names << ") values (" << values << ")";
|
|
||||||
} else if (cmd == "delete") {
|
|
||||||
os << "delete from " << table << " where id = " << id;
|
|
||||||
} else if (cmd == "update") {
|
|
||||||
vector<string> sets0;
|
|
||||||
vector<string>::iterator it;
|
|
||||||
for (it = cols.begin(); it != cols.end(); it++) {
|
|
||||||
sets0.push_back(*it + "=" + nullCheck(gArgs[*it]));
|
|
||||||
}
|
|
||||||
string sets = join(",", sets0);
|
|
||||||
os << "update " << table << " set " << sets << " where id = " << id;
|
|
||||||
} else {
|
|
||||||
LOG(ERR) << "internal error";
|
|
||||||
}
|
|
||||||
LOG(INFO) << os.str();
|
|
||||||
if (!sqlite3_command(gSubscriberRegistry.db(), os.str().c_str())) {
|
|
||||||
LOG(ERR) << "sqlite3_command problem - statement: " << os.str();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
mainTables();
|
|
||||||
}
|
|
||||||
|
|
||||||
void initHtml()
|
|
||||||
{
|
|
||||||
cout << "Content-Type: text/html\n\n";
|
|
||||||
cout << "<HTML>\n";
|
|
||||||
cout << "<HEAD>\n";
|
|
||||||
cout << "<TITLE>" << gTitle << "</TITLE>\n";
|
|
||||||
cout << "</HEAD>\n";
|
|
||||||
cout << "<BODY>\n";
|
|
||||||
cout << "<h4>" << gTitle << "</h4>\n";
|
|
||||||
time_t rawtime;
|
|
||||||
time ( &rawtime );
|
|
||||||
struct tm * timeinfo;
|
|
||||||
timeinfo = localtime ( &rawtime );
|
|
||||||
cout << "<h4>" << asctime(timeinfo) << "</h4>\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
void endHtml()
|
|
||||||
{
|
|
||||||
cout << "</BODY>\n";
|
|
||||||
cout << "</HTML>\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
void doVisibles()
|
|
||||||
{
|
|
||||||
gVisibleSipColumns = "";
|
|
||||||
map<string,string>::iterator it;
|
|
||||||
bool first = true;
|
|
||||||
for (it = gArgs.begin(); it != gArgs.end(); it++) {
|
|
||||||
if (it->first == "what") continue;
|
|
||||||
if (first) {
|
|
||||||
first = false;
|
|
||||||
} else {
|
|
||||||
gVisibleSipColumns += " ";
|
|
||||||
}
|
|
||||||
gVisibleSipColumns += it->first;
|
|
||||||
}
|
|
||||||
if (!gConfig.set("SubscriberRegistry.Manager.VisibleColumns", gVisibleSipColumns)) {
|
|
||||||
LOG(ERR) << "unable to update SubscriberRegistry.Manager.VisibleColumns";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
|
||||||
{
|
|
||||||
gSubscriberRegistry.init();
|
|
||||||
// start the html return
|
|
||||||
initHtml();
|
|
||||||
// read the config file
|
|
||||||
gVisibleSipColumns = gConfig.getStr("SubscriberRegistry.Manager.VisibleColumns");
|
|
||||||
gUrl = "/cgi/srmanager.cgi";
|
|
||||||
gTitle = gConfig.getStr("SubscriberRegistry.Manager.Title");
|
|
||||||
// connect to the database
|
|
||||||
gDatabase = gConfig.getStr("SubscriberRegistry.db");
|
|
||||||
// decode the http query
|
|
||||||
decodeQuery(gArgs);
|
|
||||||
// execute command
|
|
||||||
string what = gArgs["what"];
|
|
||||||
if (!what.length() || what == "Main") {
|
|
||||||
mainTables();
|
|
||||||
} else if (what == "Add") {
|
|
||||||
doCmd("add");
|
|
||||||
} else if (what == "Update") {
|
|
||||||
doCmd("update");
|
|
||||||
} else if (what == "Delete") {
|
|
||||||
doCmd("delete");
|
|
||||||
} else if (what == "Provision") {
|
|
||||||
gSubscriberRegistry.addUser(gArgs["imsi"].c_str(), gArgs["phonenumber"].c_str());
|
|
||||||
mainTables();
|
|
||||||
} else if (what == "Submit") {
|
|
||||||
doVisibles();
|
|
||||||
mainTables();
|
|
||||||
} else {
|
|
||||||
cout << "unrecognized what parameter<br>\n";
|
|
||||||
map<string,string>::iterator it;
|
|
||||||
for (it = gArgs.begin(); it != gArgs.end(); it++) {
|
|
||||||
cout << it->first << " -> " << it->second << "<br>\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// finish the html return
|
|
||||||
endHtml();
|
|
||||||
}
|
|
|
@ -1,11 +0,0 @@
|
||||||
PRAGMA foreign_keys=OFF;
|
|
||||||
BEGIN TRANSACTION;
|
|
||||||
CREATE TABLE IF NOT EXISTS CONFIG ( KEYSTRING TEXT UNIQUE NOT NULL, VALUESTRING TEXT, STATIC INTEGER DEFAULT 0, OPTIONAL INTEGER DEFAULT 0, COMMENTS TEXT DEFAULT '');
|
|
||||||
INSERT OR IGNORE INTO "CONFIG" VALUES('SubscriberRegistry.A3A8','./comp128',0,0,'Path to the program that implements the A3/A8 algorithm.');
|
|
||||||
INSERT OR IGNORE INTO "CONFIG" VALUES('SubscriberRegistry.Manager.Title','Subscriber Registry',0,0,'Title text to be displayed on the subscriber registry manager.');
|
|
||||||
INSERT OR IGNORE INTO "CONFIG" VALUES('SubscriberRegistry.Port','5064',0,0,'Port used by the SIP Authentication Server. NOTE: In some older releases (pre-2.8.1) this is called SIP.myPort.');
|
|
||||||
INSERT OR IGNORE INTO "CONFIG" VALUES('SubscriberRegistry.UpstreamServer','',0,0,'URL of the subscriber registry HTTP interface on the upstream server. By default, this feature is disabled. To enable, specify a server URL eg: http://localhost/cgi/subreg.cgi. To disable again, execute "unconfig SubscriberRegistry.UpstreamServer".');
|
|
||||||
INSERT OR IGNORE INTO "CONFIG" VALUES('SubscriberRegistry.db','/var/lib/asterisk/sqlite3dir/sqlite3.db',0,0,'The location of the sqlite3 database holding the subscriber registry.');
|
|
||||||
COMMIT;
|
|
||||||
|
|
||||||
|
|
|
@ -1,193 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2011 Kestrel Signal Processing, Inc.
|
|
||||||
* Copyright 2011 Range Networks, Inc.
|
|
||||||
*
|
|
||||||
* This software is distributed under the terms of the GNU Affero Public License.
|
|
||||||
* See the COPYING file in the main directory for details.
|
|
||||||
*
|
|
||||||
* This use of this software may be subject to additional restrictions.
|
|
||||||
* See the LEGAL file in the main directory for details.
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU Affero General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU Affero General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <iostream>
|
|
||||||
#include <sstream>
|
|
||||||
#include <fstream>
|
|
||||||
#include <map>
|
|
||||||
#include <vector>
|
|
||||||
#include <string>
|
|
||||||
#include <sqlite3.h>
|
|
||||||
#include <time.h>
|
|
||||||
#include "Configuration.h"
|
|
||||||
#include "Logger.h"
|
|
||||||
#include <string.h>
|
|
||||||
#include "servershare.h"
|
|
||||||
#include "SubscriberRegistry.h"
|
|
||||||
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
ConfigurationTable gConfig("/etc/OpenBTS/OpenBTS.db", "subscriberserver", getConfigurationKeys());
|
|
||||||
Log dummy("subscriberserver",gConfig.getStr("Log.Level").c_str(),LOG_LOCAL7);
|
|
||||||
|
|
||||||
// just using this for the database access
|
|
||||||
SubscriberRegistry gSubscriberRegistry;
|
|
||||||
|
|
||||||
// map of http query parameters and values
|
|
||||||
map<string,string> gArgs;
|
|
||||||
// lines of http response
|
|
||||||
vector<string> gResponse;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// retrieve a query field from args
|
|
||||||
string getArg(string label)
|
|
||||||
{
|
|
||||||
if (gArgs.find(label) == gArgs.end()) {
|
|
||||||
LOG(ERR) << "error: " << label << " missing";
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
return gArgs[label];
|
|
||||||
}
|
|
||||||
|
|
||||||
// run an sql statement through sqlite3 to get a response
|
|
||||||
void generateSqlResponse()
|
|
||||||
{
|
|
||||||
string stmts = getArg("stmts");
|
|
||||||
vector<string> vstmts;
|
|
||||||
split(';', stmts, &vstmts);
|
|
||||||
vector<string>::iterator it;
|
|
||||||
for (it = vstmts.begin(); it != vstmts.end(); it++) {
|
|
||||||
sqlite3_stmt *stmt;
|
|
||||||
if (sqlite3_prepare_statement(gSubscriberRegistry.db(), &stmt, it->c_str())) {
|
|
||||||
LOG(ERR) << "sqlite3_prepare_statement problem - statement: " << it->c_str();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
int src = sqlite3_run_query(gSubscriberRegistry.db(), stmt);
|
|
||||||
while (src == SQLITE_ROW) {
|
|
||||||
string resp = "res=";
|
|
||||||
int cols = sqlite3_column_count(stmt);
|
|
||||||
for (int i = 0; i < cols; i++) {
|
|
||||||
resp.append((const char*)sqlite3_column_text(stmt, i));
|
|
||||||
}
|
|
||||||
gResponse.push_back(resp);
|
|
||||||
src = sqlite3_run_query(gSubscriberRegistry.db(), stmt);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void sresCheck(bool b)
|
|
||||||
{
|
|
||||||
if (b) {
|
|
||||||
// SRESs match. return success (or Kc (TODO))
|
|
||||||
gResponse.push_back("status=SUCCESS");
|
|
||||||
} else {
|
|
||||||
// SRESs don't match. return failure.
|
|
||||||
gResponse.push_back("status=FAILURE");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// authenticate
|
|
||||||
void generateAuthResponse()
|
|
||||||
{
|
|
||||||
string imsi = getArg("imsi");
|
|
||||||
string randx = getArg("rand");
|
|
||||||
string sres = getArg("sres");
|
|
||||||
string kc;
|
|
||||||
bool st = authenticate(imsi, randx, sres, &kc);
|
|
||||||
sresCheck(st);
|
|
||||||
}
|
|
||||||
|
|
||||||
// generate a 128' random number
|
|
||||||
void generateRandResponse()
|
|
||||||
{
|
|
||||||
string imsi = getArg("imsi");
|
|
||||||
string randx = generateRand(imsi);
|
|
||||||
gResponse.push_back("rand=" + randx);
|
|
||||||
gResponse.push_back("imsi=" + imsi);
|
|
||||||
}
|
|
||||||
|
|
||||||
// generate our http response, putting each line of it into vector response
|
|
||||||
void generateResponse()
|
|
||||||
{
|
|
||||||
if (gArgs.find("req") == gArgs.end()) {
|
|
||||||
LOG(ERR) << "req not specified";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// check for request types
|
|
||||||
string req = gArgs["req"];
|
|
||||||
if (req == "sql") {
|
|
||||||
generateSqlResponse();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (req == "rand") {
|
|
||||||
generateRandResponse();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (req == "auth") {
|
|
||||||
generateAuthResponse();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// if none of the above, then it's an error
|
|
||||||
LOG(ERR) << "unrecognized request";
|
|
||||||
}
|
|
||||||
|
|
||||||
// write the query to the log file
|
|
||||||
void logQuery()
|
|
||||||
{
|
|
||||||
// list query key->value pairs
|
|
||||||
map<string,string>::iterator it;
|
|
||||||
LOG(INFO) << "query";
|
|
||||||
for (it = gArgs.begin(); it != gArgs.end(); it++) {
|
|
||||||
LOG(INFO) << " " << it->first << " -> " << it->second;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// write the http response from the global array @response to the log file
|
|
||||||
void logResponse()
|
|
||||||
{
|
|
||||||
LOG(INFO) << "response";
|
|
||||||
vector<string>::iterator it;
|
|
||||||
for (it = gResponse.begin(); it != gResponse.end(); it++) {
|
|
||||||
LOG(INFO) << " " << *it;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// print the http response to stdout
|
|
||||||
void respond()
|
|
||||||
{
|
|
||||||
vector<string>::iterator it;
|
|
||||||
for (it = gResponse.begin(); it != gResponse.end(); it++) {
|
|
||||||
cout << *it << endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
cout << "Content-Type: text\n\n";
|
|
||||||
srand ( time(NULL) + (int)getpid() );
|
|
||||||
// decode the http query
|
|
||||||
decodeQuery(gArgs);
|
|
||||||
// write the http query into the log file
|
|
||||||
logQuery();
|
|
||||||
// put the http response into the global array @response
|
|
||||||
generateResponse();
|
|
||||||
// write the http response to the log file
|
|
||||||
logResponse();
|
|
||||||
// print out the http response to stdout
|
|
||||||
respond();
|
|
||||||
}
|
|
|
@ -1,3 +0,0 @@
|
||||||
CommonLibs http://wush.net/svn/range/software/public/CommonLibs/trunk
|
|
||||||
sqlite3 http://wush.net/svn/range/software/public/sqlite3/trunk
|
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include "../SubscriberRegistry.h"
|
#include "../SubscriberRegistry.h"
|
||||||
#include "Configuration.h"
|
#include "Configuration.h"
|
||||||
|
#include "Utils.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
@ -14,15 +15,15 @@ SubscriberRegistry sr;
|
||||||
|
|
||||||
void foo(uint32_t n, string s)
|
void foo(uint32_t n, string s)
|
||||||
{
|
{
|
||||||
LOG(INFO) << sr.uintToString(n) << " " << s;
|
LOG(INFO) << Utils::uintToString(n) << " " << s;
|
||||||
}
|
}
|
||||||
|
|
||||||
void foo(string s)
|
void foo(string s)
|
||||||
{
|
{
|
||||||
uint64_t h;
|
uint64_t h;
|
||||||
uint64_t l;
|
uint64_t l;
|
||||||
sr.stringToUint(s, &h, &l);
|
Utils::stringToUint(s, &h, &l);
|
||||||
LOG(INFO) << sr.uintToString(h, l) << " " << s;
|
LOG(INFO) << Utils::uintToString(h, l) << " " << s;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
|
@ -39,8 +40,8 @@ int main(int argc, char **argv)
|
||||||
sr.getIMSI("clid");
|
sr.getIMSI("clid");
|
||||||
// test mapping of unknow user (so it won't be found locally)
|
// test mapping of unknow user (so it won't be found locally)
|
||||||
sr.getCLIDLocal("imsi_unknown");
|
sr.getCLIDLocal("imsi_unknown");
|
||||||
sr.getRandForAuthentication(false, "imsi_r1");
|
//sr.getRandForAuthentication(false, "imsi_r1");
|
||||||
sr.authenticate(false, "imsi_a1","rand_a1","sres_a1");
|
//sr.authenticate(false, "imsi_a1","rand_a1","sres_a1");
|
||||||
|
|
||||||
|
|
||||||
// but test the conversions
|
// but test the conversions
|
||||||
|
|
|
@ -2,7 +2,5 @@ BEGIN TRANSACTION;
|
||||||
CREATE TABLE CONFIG ( KEYSTRING TEXT UNIQUE NOT NULL, VALUESTRING TEXT, STATIC INTEGER DEFAULT 0, OPTIONAL INTEGER DEFAULT 0, COMMENTS TEXT DEFAULT '');
|
CREATE TABLE CONFIG ( KEYSTRING TEXT UNIQUE NOT NULL, VALUESTRING TEXT, STATIC INTEGER DEFAULT 0, OPTIONAL INTEGER DEFAULT 0, COMMENTS TEXT DEFAULT '');
|
||||||
INSERT INTO "CONFIG" VALUES('Log.Level','DEBUG',0,0,'');
|
INSERT INTO "CONFIG" VALUES('Log.Level','DEBUG',0,0,'');
|
||||||
INSERT INTO "CONFIG" VALUES('SubscriberRegistry.db','sr.db',0,0,'');
|
INSERT INTO "CONFIG" VALUES('SubscriberRegistry.db','sr.db',0,0,'');
|
||||||
INSERT INTO "CONFIG" VALUES('SubscriberRegistry.HTTP.Server','',0,0,'');
|
|
||||||
INSERT INTO "CONFIG" VALUES('SIP.Proxy.Registration','testing',0,0,'');
|
INSERT INTO "CONFIG" VALUES('SIP.Proxy.Registration','testing',0,0,'');
|
||||||
INSERT INTO "CONFIG" VALUES('SubscriberRegistry.UpstreamServer','',0,0,'');
|
|
||||||
COMMIT;
|
COMMIT;
|
||||||
|
|
|
@ -2,7 +2,5 @@ BEGIN TRANSACTION;
|
||||||
CREATE TABLE CONFIG ( KEYSTRING TEXT UNIQUE NOT NULL, VALUESTRING TEXT, STATIC INTEGER DEFAULT 0, OPTIONAL INTEGER DEFAULT 0, COMMENTS TEXT DEFAULT '');
|
CREATE TABLE CONFIG ( KEYSTRING TEXT UNIQUE NOT NULL, VALUESTRING TEXT, STATIC INTEGER DEFAULT 0, OPTIONAL INTEGER DEFAULT 0, COMMENTS TEXT DEFAULT '');
|
||||||
INSERT INTO "CONFIG" VALUES('Log.Level','DEBUG',0,0,'');
|
INSERT INTO "CONFIG" VALUES('Log.Level','DEBUG',0,0,'');
|
||||||
INSERT INTO "CONFIG" VALUES('SubscriberRegistry.db','sr.db',0,0,'');
|
INSERT INTO "CONFIG" VALUES('SubscriberRegistry.db','sr.db',0,0,'');
|
||||||
INSERT INTO "CONFIG" VALUES('SubscriberRegistry.HTTP.Server','testing',0,0,'');
|
|
||||||
INSERT INTO "CONFIG" VALUES('SIP.Proxy.Registration','testing',0,0,'');
|
INSERT INTO "CONFIG" VALUES('SIP.Proxy.Registration','testing',0,0,'');
|
||||||
INSERT INTO "CONFIG" VALUES('SubscriberRegistry.UpstreamServer','',0,0,'');
|
|
||||||
COMMIT;
|
COMMIT;
|
||||||
|
|
|
@ -2,7 +2,6 @@ BEGIN TRANSACTION;
|
||||||
CREATE TABLE CONFIG ( KEYSTRING TEXT UNIQUE NOT NULL, VALUESTRING TEXT, STATIC INTEGER DEFAULT 0, OPTIONAL INTEGER DEFAULT 0, COMMENTS TEXT DEFAULT '');
|
CREATE TABLE CONFIG ( KEYSTRING TEXT UNIQUE NOT NULL, VALUESTRING TEXT, STATIC INTEGER DEFAULT 0, OPTIONAL INTEGER DEFAULT 0, COMMENTS TEXT DEFAULT '');
|
||||||
INSERT INTO "CONFIG" VALUES('SubscriberRegistry.db','sr.db',0,0,'The location of the sqlite3 database holding the subscriber registry.');
|
INSERT INTO "CONFIG" VALUES('SubscriberRegistry.db','sr.db',0,0,'The location of the sqlite3 database holding the subscriber registry.');
|
||||||
INSERT INTO "CONFIG" VALUES('SubscriberRegistry.A3A8','../comp128',0,0,'');
|
INSERT INTO "CONFIG" VALUES('SubscriberRegistry.A3A8','../comp128',0,0,'');
|
||||||
INSERT INTO "CONFIG" VALUES('SubscriberRegistry.UpstreamServer','',0,0,'');
|
|
||||||
INSERT INTO "CONFIG" VALUES('Log.Level','INFO',0,0,'');
|
INSERT INTO "CONFIG" VALUES('Log.Level','INFO',0,0,'');
|
||||||
INSERT INTO "CONFIG" VALUES('Log.Level.smcommands.cpp','INFO',0,0,'');
|
INSERT INTO "CONFIG" VALUES('Log.Level.smcommands.cpp','INFO',0,0,'');
|
||||||
INSERT INTO "CONFIG" VALUES('savefile','savedqueue.txt',0,0,'');
|
INSERT INTO "CONFIG" VALUES('savefile','savedqueue.txt',0,0,'');
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,2 +0,0 @@
|
||||||
select name, username, type, context, host from sip_buddies;
|
|
||||||
select exten, dial from dialdata_table;
|
|
|
@ -1,90 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# start with a known state in DBs
|
|
||||||
rm -f /etc/OpenBTS/OpenBTS.db test.db
|
|
||||||
# initialize the config db
|
|
||||||
sqlite3 /etc/OpenBTS/OpenBTS.db < srmanager.db.init
|
|
||||||
chmod 666 /etc/OpenBTS/OpenBTS.db
|
|
||||||
# initialize the SR db
|
|
||||||
sqlite3 test.db < test.db.init
|
|
||||||
# initialize the output file
|
|
||||||
date > output.got
|
|
||||||
|
|
||||||
# Each test below enters a mark in the syslog so we can extract only
|
|
||||||
# the log entries for that test.
|
|
||||||
# Then it sets the environment variables (and stdin for POST) to duplicate
|
|
||||||
# http state, then it runs the test.
|
|
||||||
# Then it extracts the test's log entries.
|
|
||||||
# On some it then dumps the SR database.
|
|
||||||
|
|
||||||
# empty http get
|
|
||||||
logger -plocal7.Debug dwb syslog mark
|
|
||||||
REQUEST_METHOD=GET;
|
|
||||||
export REQUEST_METHOD
|
|
||||||
QUERY_STRING=
|
|
||||||
export QUERY_STRING
|
|
||||||
../srmanager.cgi >> output.got
|
|
||||||
../syslogextractor >> output.got
|
|
||||||
|
|
||||||
# http get for main page
|
|
||||||
logger -plocal7.Debug dwb syslog mark
|
|
||||||
REQUEST_METHOD=GET;
|
|
||||||
export REQUEST_METHOD
|
|
||||||
QUERY_STRING=what=Main
|
|
||||||
export QUERY_STRING
|
|
||||||
../srmanager.cgi >> output.got
|
|
||||||
../syslogextractor >> output.got
|
|
||||||
|
|
||||||
# empty http post
|
|
||||||
logger -plocal7.Debug dwb syslog mark
|
|
||||||
REQUEST_METHOD=POST;
|
|
||||||
export REQUEST_METHOD
|
|
||||||
CONTENT_LENGTH=0
|
|
||||||
export CONTENT_LENGTH
|
|
||||||
echo '' | ../srmanager.cgi >> output.got
|
|
||||||
../syslogextractor >> output.got
|
|
||||||
|
|
||||||
# http post for main page
|
|
||||||
logger -plocal7.Debug dwb syslog mark
|
|
||||||
REQUEST_METHOD=POST;
|
|
||||||
export REQUEST_METHOD
|
|
||||||
CONTENT_LENGTH=9
|
|
||||||
export CONTENT_LENGTH
|
|
||||||
echo 'what=Main' | ../srmanager.cgi >> output.got
|
|
||||||
../syslogextractor >> output.got
|
|
||||||
|
|
||||||
# http post for add
|
|
||||||
logger -plocal7.Debug dwb syslog mark
|
|
||||||
REQUEST_METHOD=POST;
|
|
||||||
export REQUEST_METHOD
|
|
||||||
CONTENT_LENGTH=55
|
|
||||||
export CONTENT_LENGTH
|
|
||||||
echo 'name=a&username=b&type=c&context=d&host=e&id=0&what=Add' | ../srmanager.cgi >> output.got
|
|
||||||
../syslogextractor >> output.got
|
|
||||||
sqlite3 test.db < ./query.sql >> output.got
|
|
||||||
|
|
||||||
# http post for delete
|
|
||||||
logger -plocal7.Debug dwb syslog mark
|
|
||||||
REQUEST_METHOD=POST;
|
|
||||||
export REQUEST_METHOD
|
|
||||||
CONTENT_LENGTH=58
|
|
||||||
export CONTENT_LENGTH
|
|
||||||
echo 'name=a&username=b&type=c&context=d&host=e&id=9&what=Delete' | ../srmanager.cgi >> output.got
|
|
||||||
../syslogextractor >> output.got
|
|
||||||
sqlite3 test.db < ./query.sql >> output.got
|
|
||||||
|
|
||||||
# http post for update
|
|
||||||
logger -plocal7.Debug dwb syslog mark
|
|
||||||
REQUEST_METHOD=POST;
|
|
||||||
export REQUEST_METHOD
|
|
||||||
CONTENT_LENGTH=35
|
|
||||||
export CONTENT_LENGTH
|
|
||||||
echo 'exten=qrs&dial=tuv&id=1&what=Update' | ../srmanager.cgi >> output.got
|
|
||||||
../syslogextractor >> output.got
|
|
||||||
sqlite3 test.db < ./query.sql >> output.got
|
|
||||||
|
|
||||||
# normalize the output file for diffing
|
|
||||||
mv output.got ootput.got
|
|
||||||
../hexmapper ootput.got > output.got
|
|
||||||
diff output.exp output.got
|
|
||||||
exit 0
|
|
|
@ -1,9 +0,0 @@
|
||||||
BEGIN TRANSACTION;
|
|
||||||
CREATE TABLE CONFIG ( KEYSTRING TEXT UNIQUE NOT NULL, VALUESTRING TEXT, STATIC INTEGER DEFAULT 0, OPTIONAL INTEGER DEFAULT 0, COMMENTS TEXT DEFAULT '');
|
|
||||||
INSERT INTO "CONFIG" VALUES('Log.Level','DEBUG',0,0,'');
|
|
||||||
INSERT INTO "CONFIG" VALUES('SubscriberRegistry.db','test.db',0,0,'');
|
|
||||||
INSERT INTO "CONFIG" VALUES('SubscriberRegistry.Manager.VisibleColumns','name username type context host',0,0,'');
|
|
||||||
INSERT INTO "CONFIG" VALUES('SubscriberRegistry.Manager.Url','http://localhost/~doug/foo.cgi',0,0,'');
|
|
||||||
INSERT INTO "CONFIG" VALUES('SubscriberRegistry.Manager.Title','Some Title',0,0,'');
|
|
||||||
COMMIT;
|
|
||||||
|
|
|
@ -1,102 +0,0 @@
|
||||||
BEGIN TRANSACTION;
|
|
||||||
CREATE TABLE dialdata_table (
|
|
||||||
id INTEGER,
|
|
||||||
exten VARCHAR(40) NOT NULL DEFAULT '',
|
|
||||||
dial VARCHAR(128) NOT NULL DEFAULT '',
|
|
||||||
PRIMARY KEY (id)
|
|
||||||
);
|
|
||||||
INSERT INTO "dialdata_table" VALUES(1,'1000','1000');
|
|
||||||
INSERT INTO "dialdata_table" VALUES(2,'1001','1001');
|
|
||||||
CREATE TABLE 'sip_buddies'
|
|
||||||
(
|
|
||||||
id integer,
|
|
||||||
name VARCHAR(80) unique not null,
|
|
||||||
context VARCHAR(80),
|
|
||||||
callingpres VARCHAR(30) DEFAULT 'allowed_not_screened',
|
|
||||||
deny VARCHAR(95),
|
|
||||||
permit VARCHAR(95),
|
|
||||||
secret VARCHAR(80),
|
|
||||||
md5secret VARCHAR(80),
|
|
||||||
remotesecret VARCHAR(250),
|
|
||||||
transport VARCHAR(10),
|
|
||||||
host VARCHAR(31) DEFAULT '' not null,
|
|
||||||
nat VARCHAR(5) DEFAULT 'no' not null,
|
|
||||||
type VARCHAR(10) DEFAULT 'friend' not null,
|
|
||||||
accountcode VARCHAR(20),
|
|
||||||
amaflags VARCHAR(13),
|
|
||||||
callgroup VARCHAR(10),
|
|
||||||
callerid VARCHAR(80),
|
|
||||||
defaultip VARCHAR(40) DEFAULT '0.0.0.0',
|
|
||||||
dtmfmode VARCHAR(7) DEFAULT 'rfc2833',
|
|
||||||
fromuser VARCHAR(80),
|
|
||||||
fromdomain VARCHAR(80),
|
|
||||||
insecure VARCHAR(4),
|
|
||||||
language CHAR(2),
|
|
||||||
mailbox VARCHAR(50),
|
|
||||||
pickupgroup VARCHAR(10),
|
|
||||||
qualify CHAR(3),
|
|
||||||
regexten VARCHAR(80),
|
|
||||||
rtptimeout CHAR(3),
|
|
||||||
rtpholdtimeout CHAR(3),
|
|
||||||
setvar VARCHAR(100),
|
|
||||||
disallow VARCHAR(100) DEFAULT 'all',
|
|
||||||
allow VARCHAR(100) DEFAULT 'ulaw' not null,
|
|
||||||
fullcontact VARCHAR(80),
|
|
||||||
ipaddr VARCHAR(40),
|
|
||||||
port int(5) DEFAULT 0,
|
|
||||||
username VARCHAR(80),
|
|
||||||
defaultuser VARCHAR(80),
|
|
||||||
subscribecontext VARCHAR(80),
|
|
||||||
directmedia VARCHAR(3),
|
|
||||||
trustrpid VARCHAR(3),
|
|
||||||
sendrpid VARCHAR(3),
|
|
||||||
progressinband VARCHAR(5),
|
|
||||||
promiscredir VARCHAR(3),
|
|
||||||
useclientcode VARCHAR(3),
|
|
||||||
callcounter VARCHAR(3),
|
|
||||||
busylevel int(11),
|
|
||||||
allowoverlap VARCHAR(3) DEFAULT 'yes',
|
|
||||||
allowsubscribe VARCHAR(3) DEFAULT 'yes',
|
|
||||||
allowtransfer VARCHAR(3) DEFAULT 'yes',
|
|
||||||
ignoresdpversion VARCHAR(3) DEFAULT 'no',
|
|
||||||
template VARCHAR(100),
|
|
||||||
videosupport VARCHAR(6) DEFAULT 'no',
|
|
||||||
maxcallbitrate int(11),
|
|
||||||
rfc2833compensate VARCHAR(3) DEFAULT 'yes',
|
|
||||||
'session-timers' VARCHAR(10) DEFAULT 'accept',
|
|
||||||
'session-expires' int(6) DEFAULT 1800,
|
|
||||||
'session-minse' int(6) DEFAULT 90,
|
|
||||||
'session-refresher' VARCHAR(3) DEFAULT 'uas',
|
|
||||||
t38pt_usertpsource VARCHAR(3),
|
|
||||||
outboundproxy VARCHAR(250),
|
|
||||||
callbackextension VARCHAR(250),
|
|
||||||
registertrying VARCHAR(3) DEFAULT 'yes',
|
|
||||||
timert1 int(6) DEFAULT 500,
|
|
||||||
timerb int(9),
|
|
||||||
qualifyfreq int(6) DEFAULT 120,
|
|
||||||
contactpermit VARCHAR(250),
|
|
||||||
contactdeny VARCHAR(250),
|
|
||||||
lastms int(11) DEFAULT 0 not null,
|
|
||||||
regserver VARCHAR(100),
|
|
||||||
regseconds int(11) DEFAULT 0 not null,
|
|
||||||
useragent VARCHAR(100),
|
|
||||||
cancallforward CHAR(3) DEFAULT 'yes' not null,
|
|
||||||
canreinvite CHAR(3) DEFAULT 'yes' not null,
|
|
||||||
mask VARCHAR(95),
|
|
||||||
musiconhold VARCHAR(100),
|
|
||||||
restrictcid CHAR(3),
|
|
||||||
calllimit int(5),
|
|
||||||
ki VARCHAR(32) DEFAULT '' not null,
|
|
||||||
rand VARCHAR(32) DEFAULT '' not null,
|
|
||||||
sres VARCHAR(32) DEFAULT '' not null,
|
|
||||||
primary key(id)
|
|
||||||
);
|
|
||||||
INSERT INTO "sip_buddies" VALUES(1,'1000','phones','allowed_not_screened',NULL,NULL,NULL,NULL,NULL,NULL,'dynamic','no','friend',NULL,NULL,NULL,NULL,'0.0.0.0','rfc2833',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'all','ulaw',NULL,NULL,0,'1000',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'yes','yes','yes','no',NULL,'no',NULL,'yes','accept',1800,90,'uas',NULL,NULL,NULL,'yes',500,NULL,120,NULL,NULL,0,NULL,0,NULL,'yes','yes',NULL,NULL,NULL,NULL,'','','');
|
|
||||||
INSERT INTO "sip_buddies" VALUES(2,'1001','phones','allowed_not_screened',NULL,NULL,NULL,NULL,NULL,NULL,'dynamic','no','friend',NULL,NULL,NULL,NULL,'0.0.0.0','rfc2833',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'all','ulaw',NULL,NULL,0,'1001',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'yes','yes','yes','no',NULL,'no',NULL,'yes','accept',1800,90,'uas',NULL,NULL,NULL,'yes',500,NULL,120,NULL,NULL,0,NULL,0,NULL,'yes','yes',NULL,NULL,NULL,NULL,'','','');
|
|
||||||
INSERT INTO "sip_buddies" VALUES(3,'imsi2',NULL,'allowed_not_screened',NULL,NULL,NULL,NULL,NULL,NULL,'','no','friend',NULL,NULL,NULL,NULL,'0.0.0.0','rfc2833',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'all','ulaw',NULL,'imsi2ipaddr',0,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'yes','yes','yes','no',NULL,'no',NULL,'yes','accept',1800,90,'uas',NULL,NULL,NULL,'yes',500,NULL,120,NULL,NULL,0,NULL,0,NULL,'yes','yes',NULL,NULL,NULL,NULL,'','','');
|
|
||||||
INSERT INTO "sip_buddies" VALUES(4,'imsi_r1',NULL,'allowed_not_screened',NULL,NULL,NULL,NULL,NULL,NULL,'','no','friend',NULL,NULL,NULL,NULL,'0.0.0.0','rfc2833',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'all','ulaw',NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'yes','yes','yes','no',NULL,'no',NULL,'yes','accept',1800,90,'uas',NULL,NULL,NULL,'yes',500,NULL,120,NULL,NULL,0,NULL,0,NULL,'yes','yes',NULL,NULL,NULL,NULL,'','','');
|
|
||||||
INSERT INTO "sip_buddies" VALUES(5,'imsi_r2',NULL,'allowed_not_screened',NULL,NULL,NULL,NULL,NULL,NULL,'','no','friend',NULL,NULL,NULL,NULL,'0.0.0.0','rfc2833',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'all','ulaw',NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'yes','yes','yes','no',NULL,'no',NULL,'yes','accept',1800,90,'uas',NULL,NULL,NULL,'yes',500,NULL,120,NULL,NULL,0,NULL,0,NULL,'yes','yes',NULL,NULL,NULL,NULL,'','12345678901234567890123456789012','');
|
|
||||||
INSERT INTO "sip_buddies" VALUES(6,'imsi_a1',NULL,'allowed_not_screened',NULL,NULL,NULL,NULL,NULL,NULL,'','no','friend',NULL,NULL,NULL,NULL,'0.0.0.0','rfc2833',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'all','ulaw',NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'yes','yes','yes','no',NULL,'no',NULL,'yes','accept',1800,90,'uas',NULL,NULL,NULL,'yes',500,NULL,120,NULL,NULL,0,NULL,0,NULL,'yes','yes',NULL,NULL,NULL,NULL,'7f4d7fbff290e20e60466bc7b5b08e4b','','');
|
|
||||||
INSERT INTO "sip_buddies" VALUES(7,'imsi_a2',NULL,'allowed_not_screened',NULL,NULL,NULL,NULL,NULL,NULL,'','no','friend',NULL,NULL,NULL,NULL,'0.0.0.0','rfc2833',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'all','ulaw',NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'yes','yes','yes','no',NULL,'no',NULL,'yes','accept',1800,90,'uas',NULL,NULL,NULL,'yes',500,NULL,120,NULL,NULL,0,NULL,0,NULL,'yes','yes',NULL,NULL,NULL,NULL,'','123','456');
|
|
||||||
INSERT INTO "sip_buddies" VALUES(8,'imsi_a3',NULL,'allowed_not_screened',NULL,NULL,NULL,NULL,NULL,NULL,'','no','friend',NULL,NULL,NULL,NULL,'0.0.0.0','rfc2833',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'all','ulaw',NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'yes','yes','yes','no',NULL,'no',NULL,'yes','accept',1800,90,'uas',NULL,NULL,NULL,'yes',500,NULL,120,NULL,NULL,0,NULL,0,NULL,'yes','yes',NULL,NULL,NULL,NULL,'','123456789012345678901234567890a3','1234567890123456789012a3');
|
|
||||||
COMMIT;
|
|
|
@ -1,133 +0,0 @@
|
||||||
Fri Mar 18 16:47:36 PDT 2011
|
|
||||||
Content-Type: text
|
|
||||||
|
|
||||||
servershare.cpp:-0-:decodeQuery: REQUEST_METHOD = GET
|
|
||||||
servershare.cpp:-0-:decodeQuery: QUERY_STRING = req=sql&stmts=insert into sip_buddies (name) values ("newname")
|
|
||||||
subscriberserver.cpp:-0-:logQuery: query
|
|
||||||
subscriberserver.cpp:-0-:logQuery: req -> sql
|
|
||||||
subscriberserver.cpp:-0-:logQuery: stmts -> insert into sip_buddies (name) values ("newname")
|
|
||||||
subscriberserver.cpp:-0-:logResponse: response
|
|
||||||
IMSI12345678901231|hexhexhexhexhexhexhexhexhexh1000|||
|
|
||||||
IMSI12345678901232||||
|
|
||||||
IMSI12345678901233|||hexhexhexhexhexhexhexhexhexh1000|
|
|
||||||
newname||||
|
|
||||||
Content-Type: text
|
|
||||||
|
|
||||||
res=IMSI12345678901232
|
|
||||||
servershare.cpp:-0-:decodeQuery: REQUEST_METHOD = GET
|
|
||||||
servershare.cpp:-0-:decodeQuery: QUERY_STRING = req=sql&stmts=select name from sip_buddies where id=2
|
|
||||||
subscriberserver.cpp:-0-:logQuery: query
|
|
||||||
subscriberserver.cpp:-0-:logQuery: req -> sql
|
|
||||||
subscriberserver.cpp:-0-:logQuery: stmts -> select name from sip_buddies where id=2
|
|
||||||
subscriberserver.cpp:-0-:logResponse: response
|
|
||||||
subscriberserver.cpp:-0-:logResponse: res=IMSI12345678901232
|
|
||||||
IMSI12345678901231|hexhexhexhexhexhexhexhexhexh1000|||
|
|
||||||
IMSI12345678901232||||
|
|
||||||
IMSI12345678901233|||hexhexhexhexhexhexhexhexhexh1000|
|
|
||||||
newname||||
|
|
||||||
Content-Type: text
|
|
||||||
|
|
||||||
rand=hexhexhexhexhexhexhexhexhexh1000
|
|
||||||
imsi=IMSI12345678901231
|
|
||||||
servershare.cpp:-0-:decodeQuery: REQUEST_METHOD = GET
|
|
||||||
servershare.cpp:-0-:decodeQuery: QUERY_STRING = req=rand&imsi=IMSI12345678901231
|
|
||||||
subscriberserver.cpp:-0-:logQuery: query
|
|
||||||
subscriberserver.cpp:-0-:logQuery: imsi -> IMSI12345678901231
|
|
||||||
subscriberserver.cpp:-0-:logQuery: req -> rand
|
|
||||||
servershare.cpp:-0-:generateRand: ki is unknown, rand is cached
|
|
||||||
subscriberserver.cpp:-0-:logResponse: response
|
|
||||||
subscriberserver.cpp:-0-:logResponse: rand=hexhexhexhexhexhexhexhexhexh1000
|
|
||||||
subscriberserver.cpp:-0-:logResponse: imsi=IMSI12345678901231
|
|
||||||
IMSI12345678901231|hexhexhexhexhexhexhexhexhexh1000|||
|
|
||||||
IMSI12345678901232||||
|
|
||||||
IMSI12345678901233|||hexhexhexhexhexhexhexhexhexh1000|
|
|
||||||
newname||||
|
|
||||||
Content-Type: text
|
|
||||||
|
|
||||||
rand=hexhexhexhexhexhexhexhexhexh1000
|
|
||||||
imsi=IMSI12345678901231
|
|
||||||
servershare.cpp:-0-:decodeQuery: REQUEST_METHOD = GET
|
|
||||||
servershare.cpp:-0-:decodeQuery: QUERY_STRING = req=rand&imsi=IMSI12345678901231
|
|
||||||
subscriberserver.cpp:-0-:logQuery: query
|
|
||||||
subscriberserver.cpp:-0-:logQuery: imsi -> IMSI12345678901231
|
|
||||||
subscriberserver.cpp:-0-:logQuery: req -> rand
|
|
||||||
servershare.cpp:-0-:generateRand: ki is unknown, rand is cached
|
|
||||||
subscriberserver.cpp:-0-:logResponse: response
|
|
||||||
subscriberserver.cpp:-0-:logResponse: rand=hexhexhexhexhexhexhexhexhexh1000
|
|
||||||
subscriberserver.cpp:-0-:logResponse: imsi=IMSI12345678901231
|
|
||||||
IMSI12345678901231|hexhexhexhexhexhexhexhexhexh1000|||
|
|
||||||
IMSI12345678901232||||
|
|
||||||
IMSI12345678901233|||hexhexhexhexhexhexhexhexhexh1000|
|
|
||||||
newname||||
|
|
||||||
Content-Type: text
|
|
||||||
|
|
||||||
rand=hexhexhexhexhexhexhexhexhexh1001
|
|
||||||
imsi=IMSI12345678901232
|
|
||||||
servershare.cpp:-0-:decodeQuery: REQUEST_METHOD = GET
|
|
||||||
servershare.cpp:-0-:decodeQuery: QUERY_STRING = req=rand&imsi=IMSI12345678901232
|
|
||||||
subscriberserver.cpp:-0-:logQuery: query
|
|
||||||
subscriberserver.cpp:-0-:logQuery: imsi -> IMSI12345678901232
|
|
||||||
subscriberserver.cpp:-0-:logQuery: req -> rand
|
|
||||||
servershare.cpp:-0-:generateRand: ki is unknown, rand is not cached
|
|
||||||
subscriberserver.cpp:-0-:logResponse: response
|
|
||||||
subscriberserver.cpp:-0-:logResponse: rand=hexhexhexhexhexhexhexhexhexh1001
|
|
||||||
subscriberserver.cpp:-0-:logResponse: imsi=IMSI12345678901232
|
|
||||||
IMSI12345678901231|hexhexhexhexhexhexhexhexhexh1000|||
|
|
||||||
IMSI12345678901232|hexhexhexhexhexhexhexhexhexh1001|||
|
|
||||||
IMSI12345678901233|||hexhexhexhexhexhexhexhexhexh1000|
|
|
||||||
newname||||
|
|
||||||
Content-Type: text
|
|
||||||
|
|
||||||
rand=hexhexhexhexhexhexhexhexhexh1001
|
|
||||||
imsi=IMSI12345678901232
|
|
||||||
servershare.cpp:-0-:decodeQuery: REQUEST_METHOD = GET
|
|
||||||
servershare.cpp:-0-:decodeQuery: QUERY_STRING = req=rand&imsi=IMSI12345678901232
|
|
||||||
subscriberserver.cpp:-0-:logQuery: query
|
|
||||||
subscriberserver.cpp:-0-:logQuery: imsi -> IMSI12345678901232
|
|
||||||
subscriberserver.cpp:-0-:logQuery: req -> rand
|
|
||||||
servershare.cpp:-0-:generateRand: ki is unknown, rand is cached
|
|
||||||
subscriberserver.cpp:-0-:logResponse: response
|
|
||||||
subscriberserver.cpp:-0-:logResponse: rand=hexhexhexhexhexhexhexhexhexh1001
|
|
||||||
subscriberserver.cpp:-0-:logResponse: imsi=IMSI12345678901232
|
|
||||||
IMSI12345678901231|hexhexhexhexhexhexhexhexhexh1000|||
|
|
||||||
IMSI12345678901232|hexhexhexhexhexhexhexhexhexh1001|||
|
|
||||||
IMSI12345678901233|||hexhexhexhexhexhexhexhexhexh1000|
|
|
||||||
newname||||
|
|
||||||
Content-Type: text
|
|
||||||
|
|
||||||
status=SUCCESS
|
|
||||||
servershare.cpp:-0-:decodeQuery: REQUEST_METHOD = GET
|
|
||||||
servershare.cpp:-0-:decodeQuery: QUERY_STRING = req=auth&imsi=IMSI12345678901233&rand=hexhexhexhexhexhexhexhexhexh1002&sres=hexh1003
|
|
||||||
subscriberserver.cpp:-0-:logQuery: query
|
|
||||||
subscriberserver.cpp:-0-:logQuery: imsi -> IMSI12345678901233
|
|
||||||
subscriberserver.cpp:-0-:logQuery: rand -> hexhexhexhexhexhexhexhexhexh1002
|
|
||||||
subscriberserver.cpp:-0-:logQuery: req -> auth
|
|
||||||
subscriberserver.cpp:-0-:logQuery: sres -> hexh1003
|
|
||||||
servershare.cpp:-0-:authenticate: ki known
|
|
||||||
servershare.cpp:-0-:authenticate: result = hexh1003
|
|
||||||
servershare.cpp:-0-:authenticate: returning = 1
|
|
||||||
subscriberserver.cpp:-0-:logResponse: response
|
|
||||||
subscriberserver.cpp:-0-:logResponse: status=SUCCESS
|
|
||||||
IMSI12345678901231|hexhexhexhexhexhexhexhexhexh1000|||
|
|
||||||
IMSI12345678901232|hexhexhexhexhexhexhexhexhexh1001|||
|
|
||||||
IMSI12345678901233|||hexhexhexhexhexhexhexhexhexh1000|
|
|
||||||
newname||||
|
|
||||||
Content-Type: text
|
|
||||||
|
|
||||||
status=FAILURE
|
|
||||||
servershare.cpp:-0-:decodeQuery: REQUEST_METHOD = GET
|
|
||||||
servershare.cpp:-0-:decodeQuery: QUERY_STRING = req=auth&imsi=IMSI12345678901233&rand=hexhexhexhexhexhexhexhexhexh1002&sres=hexh1004
|
|
||||||
subscriberserver.cpp:-0-:logQuery: query
|
|
||||||
subscriberserver.cpp:-0-:logQuery: imsi -> IMSI12345678901233
|
|
||||||
subscriberserver.cpp:-0-:logQuery: rand -> hexhexhexhexhexhexhexhexhexh1002
|
|
||||||
subscriberserver.cpp:-0-:logQuery: req -> auth
|
|
||||||
subscriberserver.cpp:-0-:logQuery: sres -> hexh1004
|
|
||||||
servershare.cpp:-0-:authenticate: ki known
|
|
||||||
servershare.cpp:-0-:authenticate: result = hexh1003
|
|
||||||
servershare.cpp:-0-:authenticate: returning = 0
|
|
||||||
subscriberserver.cpp:-0-:logResponse: response
|
|
||||||
subscriberserver.cpp:-0-:logResponse: status=FAILURE
|
|
||||||
IMSI12345678901231|hexhexhexhexhexhexhexhexhexh1000|||
|
|
||||||
IMSI12345678901232|hexhexhexhexhexhexhexhexhexh1001|||
|
|
||||||
IMSI12345678901233|||hexhexhexhexhexhexhexhexhexh1000|
|
|
||||||
newname||||
|
|
|
@ -1 +0,0 @@
|
||||||
select name, rand, sres, ki, kc from sip_buddies;
|
|
|
@ -1,89 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
|
|
||||||
rm -f /etc/OpenBTS/OpenBTS.db sr.db
|
|
||||||
sqlite3 /etc/OpenBTS/OpenBTS.db < subscriberserver.db.init
|
|
||||||
sqlite3 sr.db < sr.db.init
|
|
||||||
date > output.got
|
|
||||||
|
|
||||||
# test an sql update
|
|
||||||
logger -plocal7.Debug dwb syslog mark
|
|
||||||
REQUEST_METHOD=GET
|
|
||||||
export REQUEST_METHOD
|
|
||||||
QUERY_STRING="req=sql&stmts=insert into sip_buddies (name) values (\"newname\")"
|
|
||||||
export QUERY_STRING
|
|
||||||
../subscriberserver.cgi >> output.got
|
|
||||||
../syslogextractor >> output.got
|
|
||||||
sqlite3 sr.db < query.sql >> output.got
|
|
||||||
|
|
||||||
# test an sql query
|
|
||||||
logger -plocal7.Debug dwb syslog mark
|
|
||||||
REQUEST_METHOD=GET
|
|
||||||
export REQUEST_METHOD
|
|
||||||
QUERY_STRING="req=sql&stmts=select name from sip_buddies where id=2"
|
|
||||||
export QUERY_STRING
|
|
||||||
../subscriberserver.cgi >> output.got
|
|
||||||
../syslogextractor >> output.got
|
|
||||||
sqlite3 sr.db < query.sql >> output.got
|
|
||||||
|
|
||||||
# Some rand and auth tests just to see that things are connected ok.
|
|
||||||
# No need for exhaustive testing because the code is shared, and
|
|
||||||
# tested better elsewhere.
|
|
||||||
|
|
||||||
logger -plocal7.Debug dwb syslog mark
|
|
||||||
REQUEST_METHOD=GET
|
|
||||||
export REQUEST_METHOD
|
|
||||||
QUERY_STRING="req=rand&imsi=IMSI12345678901231"
|
|
||||||
export QUERY_STRING
|
|
||||||
../subscriberserver.cgi >> output.got
|
|
||||||
../syslogextractor >> output.got
|
|
||||||
sqlite3 sr.db < query.sql >> output.got
|
|
||||||
|
|
||||||
logger -plocal7.Debug dwb syslog mark
|
|
||||||
REQUEST_METHOD=GET
|
|
||||||
export REQUEST_METHOD
|
|
||||||
QUERY_STRING="req=rand&imsi=IMSI12345678901231"
|
|
||||||
export QUERY_STRING
|
|
||||||
../subscriberserver.cgi >> output.got
|
|
||||||
../syslogextractor >> output.got
|
|
||||||
sqlite3 sr.db < query.sql >> output.got
|
|
||||||
|
|
||||||
logger -plocal7.Debug dwb syslog mark
|
|
||||||
REQUEST_METHOD=GET
|
|
||||||
export REQUEST_METHOD
|
|
||||||
QUERY_STRING="req=rand&imsi=IMSI12345678901232"
|
|
||||||
export QUERY_STRING
|
|
||||||
../subscriberserver.cgi >> output.got
|
|
||||||
../syslogextractor >> output.got
|
|
||||||
sqlite3 sr.db < query.sql >> output.got
|
|
||||||
|
|
||||||
logger -plocal7.Debug dwb syslog mark
|
|
||||||
REQUEST_METHOD=GET
|
|
||||||
export REQUEST_METHOD
|
|
||||||
QUERY_STRING="req=rand&imsi=IMSI12345678901232"
|
|
||||||
export QUERY_STRING
|
|
||||||
../subscriberserver.cgi >> output.got
|
|
||||||
../syslogextractor >> output.got
|
|
||||||
sqlite3 sr.db < query.sql >> output.got
|
|
||||||
|
|
||||||
logger -plocal7.Debug dwb syslog mark
|
|
||||||
REQUEST_METHOD=GET
|
|
||||||
export REQUEST_METHOD
|
|
||||||
QUERY_STRING="req=auth&imsi=IMSI12345678901233&rand=d76fe9a5839089a2ebeb269b46bf46ff&sres=726259AF"
|
|
||||||
export QUERY_STRING
|
|
||||||
../subscriberserver.cgi >> output.got
|
|
||||||
../syslogextractor >> output.got
|
|
||||||
sqlite3 sr.db < query.sql >> output.got
|
|
||||||
|
|
||||||
logger -plocal7.Debug dwb syslog mark
|
|
||||||
REQUEST_METHOD=GET
|
|
||||||
export REQUEST_METHOD
|
|
||||||
QUERY_STRING="req=auth&imsi=IMSI12345678901233&rand=d76fe9a5839089a2ebeb269b46bf46ff&sres=726259A0"
|
|
||||||
export QUERY_STRING
|
|
||||||
../subscriberserver.cgi >> output.got
|
|
||||||
../syslogextractor >> output.got
|
|
||||||
sqlite3 sr.db < query.sql >> output.got
|
|
||||||
|
|
||||||
mv output.got ootput.got
|
|
||||||
../hexmapper ootput.got > output.got
|
|
||||||
diff output.exp output.got
|
|
||||||
exit 0
|
|
|
@ -1,101 +0,0 @@
|
||||||
BEGIN TRANSACTION;
|
|
||||||
CREATE TABLE dialdata_table (
|
|
||||||
id INTEGER,
|
|
||||||
exten VARCHAR(40) NOT NULL DEFAULT '',
|
|
||||||
dial VARCHAR(128) NOT NULL DEFAULT '',
|
|
||||||
PRIMARY KEY (id)
|
|
||||||
);
|
|
||||||
INSERT INTO "dialdata_table" VALUES(1,'1000','1000');
|
|
||||||
INSERT INTO "dialdata_table" VALUES(2,'1001','1001');
|
|
||||||
INSERT INTO "dialdata_table" VALUES(3,'clid1','imsi1');
|
|
||||||
CREATE TABLE 'sip_buddies'
|
|
||||||
(
|
|
||||||
id integer,
|
|
||||||
name VARCHAR(80) unique not null,
|
|
||||||
context VARCHAR(80),
|
|
||||||
callingpres VARCHAR(30) DEFAULT 'allowed_not_screened',
|
|
||||||
deny VARCHAR(95),
|
|
||||||
permit VARCHAR(95),
|
|
||||||
secret VARCHAR(80),
|
|
||||||
md5secret VARCHAR(80),
|
|
||||||
remotesecret VARCHAR(250),
|
|
||||||
transport VARCHAR(10),
|
|
||||||
host VARCHAR(31) DEFAULT '' not null,
|
|
||||||
nat VARCHAR(5) DEFAULT 'no' not null,
|
|
||||||
type VARCHAR(10) DEFAULT 'friend' not null,
|
|
||||||
accountcode VARCHAR(20),
|
|
||||||
amaflags VARCHAR(13),
|
|
||||||
callgroup VARCHAR(10),
|
|
||||||
callerid VARCHAR(80),
|
|
||||||
defaultip VARCHAR(40) DEFAULT '0.0.0.0',
|
|
||||||
dtmfmode VARCHAR(7) DEFAULT 'rfc2833',
|
|
||||||
fromuser VARCHAR(80),
|
|
||||||
fromdomain VARCHAR(80),
|
|
||||||
insecure VARCHAR(4),
|
|
||||||
language CHAR(2),
|
|
||||||
mailbox VARCHAR(50),
|
|
||||||
pickupgroup VARCHAR(10),
|
|
||||||
qualify CHAR(3),
|
|
||||||
regexten VARCHAR(80),
|
|
||||||
rtptimeout CHAR(3),
|
|
||||||
rtpholdtimeout CHAR(3),
|
|
||||||
setvar VARCHAR(100),
|
|
||||||
disallow VARCHAR(100) DEFAULT 'all',
|
|
||||||
allow VARCHAR(100) DEFAULT 'ulaw' not null,
|
|
||||||
fullcontact VARCHAR(80),
|
|
||||||
ipaddr VARCHAR(40),
|
|
||||||
port int(5) DEFAULT 0,
|
|
||||||
username VARCHAR(80),
|
|
||||||
defaultuser VARCHAR(80),
|
|
||||||
subscribecontext VARCHAR(80),
|
|
||||||
directmedia VARCHAR(3),
|
|
||||||
trustrpid VARCHAR(3),
|
|
||||||
sendrpid VARCHAR(3),
|
|
||||||
progressinband VARCHAR(5),
|
|
||||||
promiscredir VARCHAR(3),
|
|
||||||
useclientcode VARCHAR(3),
|
|
||||||
callcounter VARCHAR(3),
|
|
||||||
busylevel int(11),
|
|
||||||
allowoverlap VARCHAR(3) DEFAULT 'yes',
|
|
||||||
allowsubscribe VARCHAR(3) DEFAULT 'yes',
|
|
||||||
allowtransfer VARCHAR(3) DEFAULT 'yes',
|
|
||||||
ignoresdpversion VARCHAR(3) DEFAULT 'no',
|
|
||||||
template VARCHAR(100),
|
|
||||||
videosupport VARCHAR(6) DEFAULT 'no',
|
|
||||||
maxcallbitrate int(11),
|
|
||||||
rfc2833compensate VARCHAR(3) DEFAULT 'yes',
|
|
||||||
'session-timers' VARCHAR(10) DEFAULT 'accept',
|
|
||||||
'session-expires' int(6) DEFAULT 1800,
|
|
||||||
'session-minse' int(6) DEFAULT 90,
|
|
||||||
'session-refresher' VARCHAR(3) DEFAULT 'uas',
|
|
||||||
t38pt_usertpsource VARCHAR(3),
|
|
||||||
outboundproxy VARCHAR(250),
|
|
||||||
callbackextension VARCHAR(250),
|
|
||||||
registertrying VARCHAR(3) DEFAULT 'yes',
|
|
||||||
timert1 int(6) DEFAULT 500,
|
|
||||||
timerb int(9),
|
|
||||||
qualifyfreq int(6) DEFAULT 120,
|
|
||||||
contactpermit VARCHAR(250),
|
|
||||||
contactdeny VARCHAR(250),
|
|
||||||
lastms int(11) DEFAULT 0 not null,
|
|
||||||
regserver VARCHAR(100),
|
|
||||||
regseconds int(11) DEFAULT 0 not null,
|
|
||||||
useragent VARCHAR(100),
|
|
||||||
cancallforward CHAR(3) DEFAULT 'yes' not null,
|
|
||||||
canreinvite CHAR(3) DEFAULT 'yes' not null,
|
|
||||||
mask VARCHAR(95),
|
|
||||||
musiconhold VARCHAR(100),
|
|
||||||
restrictcid CHAR(3),
|
|
||||||
calllimit int(5),
|
|
||||||
rand varchar(33) default '',
|
|
||||||
sres varchar(33) default '',
|
|
||||||
ki varchar(33) default '',
|
|
||||||
kc varchar(33) default '',
|
|
||||||
primary key(id)
|
|
||||||
);
|
|
||||||
|
|
||||||
insert into sip_buddies (name,rand,sres,ki,kc) values ('IMSI12345678901231','48091124c1155bd95c6f1860dc66ce92','','','');
|
|
||||||
insert into sip_buddies (name,rand,sres,ki,kc) values ('IMSI12345678901232','','','','');
|
|
||||||
insert into sip_buddies (name,rand,sres,ki,kc) values ('IMSI12345678901233','','','48091124c1155bd95c6f1860dc66ce92','');
|
|
||||||
|
|
||||||
COMMIT;
|
|
|
@ -1,7 +0,0 @@
|
||||||
BEGIN TRANSACTION;
|
|
||||||
CREATE TABLE CONFIG ( KEYSTRING TEXT UNIQUE NOT NULL, VALUESTRING TEXT, STATIC INTEGER DEFAULT 0, OPTIONAL INTEGER DEFAULT 0, COMMENTS TEXT DEFAULT '');
|
|
||||||
INSERT INTO "CONFIG" VALUES('SubscriberRegistry.db','sr.db',0,0,'');
|
|
||||||
INSERT INTO "CONFIG" VALUES('SubscriberRegistry.A3A8','../comp128',0,0,'');
|
|
||||||
INSERT INTO "CONFIG" VALUES('SubscriberRegistry.UpstreamServer','',0,0,'');
|
|
||||||
INSERT INTO "CONFIG" VALUES('Log.Level','DEBUG',0,0,'');
|
|
||||||
COMMIT;
|
|
Loading…
Reference in New Issue