Hinzugefügt:
authorms <ms@ea5c0bd1-69bd-2848-81d8-4f18e57aeed8>
Fri, 14 Apr 2006 23:12:47 +0000 (23:12 +0000)
committerms <ms@ea5c0bd1-69bd-2848-81d8-4f18e57aeed8>
Fri, 14 Apr 2006 23:12:47 +0000 (23:12 +0000)
  * Asterisk - mit Zaptel/LibPRI/BRISTUFF/app_fax
  * Spandsp
  * LibTIFF
  * LibXML2
  * eDonkey-commandline-client
Geändert:
  * busybox - tar-parameter zurückgesetzt
  * postfix hat Beta-Status-1

git-svn-id: http://svn.ipfire.org/svn/ipfire/trunk@101 ea5c0bd1-69bd-2848-81d8-4f18e57aeed8

33 files changed:
doc/packages-list.txt
lfs/asterisk [new file with mode: 0644]
lfs/busybox
lfs/edonkeyclc [new file with mode: 0644]
lfs/libtiff [new file with mode: 0644]
lfs/libxml2 [new file with mode: 0644]
lfs/postfix
lfs/spandsp [new file with mode: 0644]
make.sh
src/paks/asterisk/CONFFILES [new file with mode: 0644]
src/paks/asterisk/ROOTFILES [new file with mode: 0644]
src/paks/asterisk/install.sh [new file with mode: 0644]
src/paks/asterisk/uninstall.sh [new file with mode: 0644]
src/paks/edonkeyclc/CONFFILES [new file with mode: 0644]
src/paks/edonkeyclc/ROOTFILES [new file with mode: 0644]
src/paks/edonkeyclc/install.sh [new file with mode: 0644]
src/paks/edonkeyclc/uninstall.sh [new file with mode: 0644]
src/paks/libtiff/CONFFILES [new file with mode: 0644]
src/paks/libtiff/ROOTFILES [new file with mode: 0644]
src/paks/libtiff/install.sh [new file with mode: 0644]
src/paks/libtiff/uninstall.sh [new file with mode: 0644]
src/paks/libxml2/CONFFILES [new file with mode: 0644]
src/paks/libxml2/ROOTFILES [new file with mode: 0644]
src/paks/libxml2/install.sh [new file with mode: 0644]
src/paks/libxml2/uninstall.sh [new file with mode: 0644]
src/paks/spandsp/CONFFILES [new file with mode: 0644]
src/paks/spandsp/ROOTFILES [new file with mode: 0644]
src/paks/spandsp/install.sh [new file with mode: 0644]
src/paks/spandsp/uninstall.sh [new file with mode: 0644]
src/patches/asterisk-1.2.4-iax2-bristuff-0.3.0-PRE-1l.patch [new file with mode: 0644]
src/patches/asterisk-1.2.4-ipfire-bristuff-0.3.0-PRE-1l.patch [new file with mode: 0644]
src/patches/asterisk-1.2.4-libpri-bristuff-0.3.0-PRE-1l.patch [new file with mode: 0644]
src/patches/asterisk-1.2.4-zaptel-bristuff-0.3.0-PRE-1l.patch [new file with mode: 0644]

index bd1d335..b2ab7cd 100644 (file)
@@ -20,6 +20,8 @@
   * apache_1.3.34
   * arping-2.05
   * as86-0.16.17
+  * asterisk-1.2.4
+  * asterisk-1.2.4_1st
   * autoconf-2.59
   * automake-1.8.4
   * bash-2.05b
   * libnet-1.1.2.1
   * libpcap-0.8.3
   * libpng-1.2.8
+  * libpri-1.2.2
   * libsafe_2.0-16
   * libtool-1.5.6
   * libusb-0.1.7
   * libwww-perl-5.803
+  * libxml2-2.6.22
   * linux-2.4.31
   * linux-atm-2.4.1
   * logrotate-3.7
   * shadow-4.0.4.1
   * slang-1.4.5-mini
   * snort-2.3.3
+  * spandsp-0.0.2pre25
   * speedtouch-1.2
   * squid-2.5.STABLE13
   * squid-graph-3.1
   * tar-1.13.25
   * tcpdump-3.8.3
   * texinfo-4.7
+  * tiff-3.8.2
   * traceroute-1.4a12
   * uClibc-0.9.26
   * unzip552
   * wireless_tools.27
   * xampp-linux-1.5.1
   * xinetd-2.3.14
+  * zaptel-1.2.3_1st
   * zlib-1.2.3
diff --git a/lfs/asterisk b/lfs/asterisk
new file mode 100644 (file)
index 0000000..8c4bf7a
--- /dev/null
@@ -0,0 +1,145 @@
+###############################################################################
+# This file is part of the IPCop Firewall.                                    #
+#                                                                             #
+# IPCop 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.                                         #
+#                                                                             #
+# IPCop 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 IPCop; if not, write to the Free Software                        #
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA    #
+#                                                                             #
+# Makefiles are based on LFSMake, which is                                    #
+# Copyright (C) 2002 Rod Roard <rod@sunsetsystems.com>                        #
+#                                                                             #
+###############################################################################
+
+###############################################################################
+# Definitions
+###############################################################################
+
+include Config
+
+VER        = 1.2.4
+
+THISAPP    = asterisk-$(VER)
+DL_FILE    = $(THISAPP).tar.gz
+DL_FROM    = http://www.asterisk-support.de/mirror/asterisk-1.2.4
+DIR_APP    = $(DIR_SRC)/$(THISAPP)
+TARGET     = $(DIR_INFO)/$(THISAPP)
+
+ASTERISK   = $(THISAPP)
+ZAPTEL     = zaptel-1.2.3
+BRISTUFF   = bristuff-0.3.0-PRE-1l
+LIBPRI     = libpri-1.2.2
+SPANDSP    = spandsp-0.0.2pre25
+
+###############################################################################
+# Top-level Rules
+###############################################################################
+
+objects = $(DL_FILE) \
+          $(ZAPTEL).tar.gz \
+          $(BRISTUFF).tar.gz \
+          $(LIBPRI).tar.gz \
+          app_rxfax.c \
+          app_txfax.c \
+          apps_Makefile.patch
+
+$(DL_FILE) = $(DL_FROM)/$(DL_FILE)
+$(ZAPTEL).tar.gz = http://www.asterisk-support.de/mirror/zaptel/$(ZAPTEL).tar.gz
+$(BRISTUFF).tar.gz = http://www.junghanns.net/downloads/$(BRISTUFF).tar.gz
+$(LIBPRI).tar.gz = http://www.asterisk-support.de/mirror/libpri/$(LIBPRI).tar.gz
+app_rxfax.c = http://soft-switch.org/downloads/spandsp/$(SPANDSP)/asterisk-1.2.x/app_rxfax.c
+app_txfax.c = http://soft-switch.org/downloads/spandsp/$(SPANDSP)/asterisk-1.2.x/app_txfax.c
+apps_Makefile.patch = http://soft-switch.org/downloads/spandsp/$(SPANDSP)/asterisk-1.2.x/apps_Makefile.patch
+
+$(DL_FILE)_MD5 = 14721abdc85fc3381db275b61dffce2d
+$(ZAPTEL).tar.gz_MD5 = 9bcb705458f9b20a9644310298a9cd4d
+$(BRISTUFF).tar.gz_MD5 = 81941539b03b6ac8f193b33451e0a740
+$(LIBPRI).tar.gz_MD5 = efce9c3699110588df5e4cf09eae01d9
+app_rxfax.c_MD5 = ab6983b51c412883545b36993d704999
+app_txfax.c_MD5 = 8c8fcb263b76897022b4c28052a7b439
+apps_Makefile.patch_MD5 = 6b0faa7a7cf8613962b17c23ee5a1583
+
+install : $(TARGET)
+
+check : $(patsubst %,$(DIR_CHK)/%,$(objects))
+
+download :$(patsubst %,$(DIR_DL)/%,$(objects))
+
+md5 : $(subst %,%_MD5,$(objects))
+
+dist: 
+       make-packages.sh asterisk $(THISAPP)
+
+###############################################################################
+# Downloading, checking, md5sum
+###############################################################################
+
+$(patsubst %,$(DIR_CHK)/%,$(objects)) :
+       @$(CHECK)
+
+$(patsubst %,$(DIR_DL)/%,$(objects)) :
+       @$(LOAD)
+
+$(subst %,%_MD5,$(objects)) :
+       @$(MD5)
+
+###############################################################################
+# Installation Details
+###############################################################################
+
+$(TARGET) : $(patsubst %,$(DIR_DL)/%,$(objects))
+       @$(PREBUILD)
+       @rm -rf $(DIR_SRC)/$(BRISTUFF)
+       # Decompress the source-code
+       cd $(DIR_SRC) && \
+       tar zxf $(DIR_DL)/$(BRISTUFF).tar.gz -C $(DIR_SRC) && \
+       cd $(DIR_SRC)/$(BRISTUFF) && \
+       tar xfz $(DIR_DL)/$(ZAPTEL).tar.gz && \
+       tar xfz $(DIR_DL)/$(LIBPRI).tar.gz && \
+       tar xfz $(DIR_DL)/$(ASTERISK).tar.gz
+       # Build Zaptel
+       cd $(DIR_SRC)/$(BRISTUFF)/$(ZAPTEL) && \
+       patch -Np1 < $(DIR_SRC)/src/patches/asterisk-1.2.4-zaptel-$(BRISTUFF).patch && \
+       make clean all KVERS=$(KVER) && \
+       make install KVERS=$(KVER)
+       # Build Libpri
+       cd $(DIR_SRC)/$(BRISTUFF)/$(LIBPRI) && \
+       patch -Np1 < $(DIR_SRC)/src/patches/asterisk-1.2.4-libpri-$(BRISTUFF).patch && \
+       make clean all KVERS=$(KVER) && \
+       make install KVERS=$(KVER)
+       # Build qozap
+       cd $(DIR_SRC)/$(BRISTUFF)/qozap && \
+       make clean linux24 && \
+       install -D -m 644 qozap.o /lib/modules/$(KVER)/misc/qozap.o
+       # Build cwain
+       cd $(DIR_SRC)/$(BRISTUFF)/cwain && \
+       make clean linux24 && \
+       install -D -m 644 cwain.o /lib/modules/$(KVER)/misc/cwain.o
+       # Build zaphfc
+       cd $(DIR_SRC)/$(BRISTUFF)/zaphfc && \
+       make clean linux24 && \
+       install -D -m 644 zaphfc.o /lib/modules/$(KVER)/misc/zaphfc.o
+       # Build Asterisk
+       cd $(DIR_SRC)/$(BRISTUFF)/$(ASTERISK) && \
+       patch -Np1 < $(DIR_SRC)/src/patches/$(THISAPP)-ipfire-$(BRISTUFF).patch && \
+       patch -Np1 < $(DIR_SRC)/src/patches/$(THISAPP)-iax2-$(BRISTUFF).patch && \
+       cp -fv $(DIR_DL)/app_{r,t}xfax.c $(DIR_SRC)/$(BRISTUFF)/$(ASTERISK)/apps && \
+       cd $(DIR_SRC)/$(BRISTUFF)/$(ASTERISK)/apps && \
+       patch -Np1 < $(DIR_DL)/apps_Makefile.patch && \
+       cd $(DIR_SRC)/$(BRISTUFF)/$(ASTERISK) && \
+       make clean && \
+       make all && \
+       make install && \
+       make samples
+       @rm -rf $(DIR_SRC)/$(BRISTUFF)
+       @$(POSTBUILD)
+
index 7df7c61..a9027c4 100644 (file)
@@ -90,7 +90,7 @@ $(TARGET) : $(patsubst %,$(DIR_DL)/%,$(objects))
                cd $(DIR_APP) && sed -i -e 's/#define BB_RMMOD//' Config.h; \
                cd $(DIR_APP) && sed -i -e 's/#define BB_MODPROBE//' Config.h; \
        fi
-       cd $(DIR_APP) && sed -i -e 's/enum { NAME_SIZE = 100 };/enum { NAME_SIZE = 150 };/' tar.c; \
+#      cd $(DIR_APP) && sed -i -e 's/enum { NAME_SIZE = 100 };/enum { NAME_SIZE = 150 };/' tar.c; \
        
        cd $(DIR_APP) && make
        -mkdir -p /install/initrd/bin
diff --git a/lfs/edonkeyclc b/lfs/edonkeyclc
new file mode 100644 (file)
index 0000000..c2cabca
--- /dev/null
@@ -0,0 +1,82 @@
+###############################################################################
+# This file is part of the IPCop Firewall.                                    #
+#                                                                             #
+# IPCop 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.                                         #
+#                                                                             #
+# IPCop 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 IPCop; if not, write to the Free Software                        #
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA    #
+#                                                                             #
+# Makefiles are based on LFSMake, which is                                    #
+# Copyright (C) 2002 Rod Roard <rod@sunsetsystems.com>                        #
+#                                                                             #
+# Modifications by:                                                           #
+# ??-12-2003 Mark Wormgoor < mark@wormgoor.com>                               #
+#          - Modified Makefile for IPCop build                                #
+#                                                                             #
+###############################################################################
+
+###############################################################################
+# Definitions
+###############################################################################
+
+include Config
+
+VER        = 1.3.0
+
+THISAPP    = edonkeyclc_$(VER)_i386
+DL_FILE    = $(THISAPP).tar.gz
+DL_FROM    = http://www.zen18864.zen.co.uk/edonkey/1.3.0
+DIR_APP    = $(DIR_SRC)/$(THISAPP)
+TARGET     = $(DIR_INFO)/$(THISAPP)
+
+###############################################################################
+# Top-level Rules
+###############################################################################
+
+objects = $(DL_FILE)
+
+$(DL_FILE) = $(DL_FROM)/$(DL_FILE)
+
+$(DL_FILE)_MD5 = 46ced65b8bde60db234ad781861139c8
+
+install : $(TARGET)
+
+check : $(patsubst %,$(DIR_CHK)/%,$(objects))
+
+download :$(patsubst %,$(DIR_DL)/%,$(objects))
+
+md5 : $(subst %,%_MD5,$(objects))
+
+dist: 
+       make-packages.sh edonkeyclc $(THISAPP)-ipfire-beta-1
+
+###############################################################################
+# Downloading, checking, md5sum
+###############################################################################
+
+$(patsubst %,$(DIR_CHK)/%,$(objects)) :
+       @$(CHECK)
+
+$(patsubst %,$(DIR_DL)/%,$(objects)) :
+       @$(LOAD)
+
+$(subst %,%_MD5,$(objects)) :
+       @$(MD5)
+
+###############################################################################
+# Installation Details
+###############################################################################
+
+$(TARGET) : $(patsubst %,$(DIR_DL)/%,$(objects))
+       @$(PREBUILD)
+       cd $(DIR_SRC) && tar zxf $(DIR_DL)/$(DL_FILE) -C /
+       @$(POSTBUILD)
diff --git a/lfs/libtiff b/lfs/libtiff
new file mode 100644 (file)
index 0000000..658d6a2
--- /dev/null
@@ -0,0 +1,88 @@
+###############################################################################
+# This file is part of the IPCop Firewall.                                    #
+#                                                                             #
+# IPCop 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.                                         #
+#                                                                             #
+# IPCop 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 IPCop; if not, write to the Free Software                        #
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA    #
+#                                                                             #
+# Makefiles are based on LFSMake, which is                                    #
+# Copyright (C) 2002 Rod Roard <rod@sunsetsystems.com>                        #
+#                                                                             #
+# Modifications by:                                                           #
+# ??-12-2003 Mark Wormgoor < mark@wormgoor.com>                               #
+#          - Modified Makefile for IPCop build                                #
+#                                                                             #
+# $Id: ntp,v 1.6.2.3 2005/02/05 15:38:15 gespinasse Exp $
+#                                                                             #
+###############################################################################
+
+###############################################################################
+# Definitions
+###############################################################################
+
+include Config
+
+VER        = 3.8.2
+
+THISAPP    = tiff-$(VER)
+DL_FILE    = $(THISAPP).tar.gz
+DL_FROM    = ftp://ftp.remotesensing.org/libtiff
+DIR_APP    = $(DIR_SRC)/$(THISAPP)
+TARGET     = $(DIR_INFO)/$(THISAPP)
+
+###############################################################################
+# Top-level Rules
+###############################################################################
+
+objects = $(DL_FILE)
+
+$(DL_FILE) = $(DL_FROM)/$(DL_FILE)
+
+$(DL_FILE)_MD5 = fbb6f446ea4ed18955e2714934e5b698
+
+install : $(TARGET)
+
+check : $(patsubst %,$(DIR_CHK)/%,$(objects))
+
+download :$(patsubst %,$(DIR_DL)/%,$(objects))
+
+md5 : $(subst %,%_MD5,$(objects))
+
+dist: 
+       make-packages.sh libtiff $(THISAPP)-ipfire-beta-1
+
+###############################################################################
+# Downloading, checking, md5sum
+###############################################################################
+
+$(patsubst %,$(DIR_CHK)/%,$(objects)) :
+       @$(CHECK)
+
+$(patsubst %,$(DIR_DL)/%,$(objects)) :
+       @$(LOAD)
+
+$(subst %,%_MD5,$(objects)) :
+       @$(MD5)
+
+###############################################################################
+# Installation Details
+###############################################################################
+
+$(TARGET) : $(patsubst %,$(DIR_DL)/%,$(objects))
+       @$(PREBUILD)
+       @rm -rf $(DIR_APP) && cd $(DIR_SRC) && tar zxf $(DIR_DL)/$(DL_FILE)
+       cd $(DIR_APP) && ./configure --prefix=/usr
+       cd $(DIR_APP) && make
+       cd $(DIR_APP) && make install
+       @rm -rf $(DIR_APP)
+       @$(POSTBUILD)
diff --git a/lfs/libxml2 b/lfs/libxml2
new file mode 100644 (file)
index 0000000..338c2f8
--- /dev/null
@@ -0,0 +1,88 @@
+###############################################################################
+# This file is part of the IPCop Firewall.                                    #
+#                                                                             #
+# IPCop 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.                                         #
+#                                                                             #
+# IPCop 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 IPCop; if not, write to the Free Software                        #
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA    #
+#                                                                             #
+# Makefiles are based on LFSMake, which is                                    #
+# Copyright (C) 2002 Rod Roard <rod@sunsetsystems.com>                        #
+#                                                                             #
+# Modifications by:                                                           #
+# ??-12-2003 Mark Wormgoor < mark@wormgoor.com>                               #
+#          - Modified Makefile for IPCop build                                #
+#                                                                             #
+# $Id: ntp,v 1.6.2.3 2005/02/05 15:38:15 gespinasse Exp $
+#                                                                             #
+###############################################################################
+
+###############################################################################
+# Definitions
+###############################################################################
+
+include Config
+
+VER        = 2.6.22
+
+THISAPP    = libxml2-$(VER)
+DL_FILE    = $(THISAPP).tar.gz
+DL_FROM    = ftp://xmlsoft.org/libxml2
+DIR_APP    = $(DIR_SRC)/$(THISAPP)
+TARGET     = $(DIR_INFO)/$(THISAPP)
+
+###############################################################################
+# Top-level Rules
+###############################################################################
+
+objects = $(DL_FILE)
+
+$(DL_FILE) = $(DL_FROM)/$(DL_FILE)
+
+$(DL_FILE)_MD5 = 1db8d06b4f49a665a8f47dc6d94450e6
+
+install : $(TARGET)
+
+check : $(patsubst %,$(DIR_CHK)/%,$(objects))
+
+download :$(patsubst %,$(DIR_DL)/%,$(objects))
+
+md5 : $(subst %,%_MD5,$(objects))
+
+dist: 
+       make-packages.sh libxml2 $(THISAPP)-ipfire-beta-1
+
+###############################################################################
+# Downloading, checking, md5sum
+###############################################################################
+
+$(patsubst %,$(DIR_CHK)/%,$(objects)) :
+       @$(CHECK)
+
+$(patsubst %,$(DIR_DL)/%,$(objects)) :
+       @$(LOAD)
+
+$(subst %,%_MD5,$(objects)) :
+       @$(MD5)
+
+###############################################################################
+# Installation Details
+###############################################################################
+
+$(TARGET) : $(patsubst %,$(DIR_DL)/%,$(objects))
+       @$(PREBUILD)
+       @rm -rf $(DIR_APP) && cd $(DIR_SRC) && tar zxf $(DIR_DL)/$(DL_FILE)
+       cd $(DIR_APP) && ./configure --prefix=/usr
+       cd $(DIR_APP) && make
+       cd $(DIR_APP) && make install
+       @rm -rf $(DIR_APP)
+       @$(POSTBUILD)
index 3524473..b92f78b 100644 (file)
@@ -59,7 +59,7 @@ download :$(patsubst %,$(DIR_DL)/%,$(objects))
 md5 : $(subst %,%_MD5,$(objects))
 
 dist: 
-       make-packages.sh postfix $(THISAPP)
+       make-packages.sh postfix $(THISAPP)-ipfire-beta-1
 
 ###############################################################################
 # Downloading, checking, md5sum
diff --git a/lfs/spandsp b/lfs/spandsp
new file mode 100644 (file)
index 0000000..83c0e3b
--- /dev/null
@@ -0,0 +1,88 @@
+###############################################################################
+# This file is part of the IPCop Firewall.                                    #
+#                                                                             #
+# IPCop 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.                                         #
+#                                                                             #
+# IPCop 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 IPCop; if not, write to the Free Software                        #
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA    #
+#                                                                             #
+# Makefiles are based on LFSMake, which is                                    #
+# Copyright (C) 2002 Rod Roard <rod@sunsetsystems.com>                        #
+#                                                                             #
+# Modifications by:                                                           #
+# ??-12-2003 Mark Wormgoor < mark@wormgoor.com>                               #
+#          - Modified Makefile for IPCop build                                #
+#                                                                             #
+# $Id: ntp,v 1.6.2.3 2005/02/05 15:38:15 gespinasse Exp $
+#                                                                             #
+###############################################################################
+
+###############################################################################
+# Definitions
+###############################################################################
+
+include Config
+
+VER        = 0.0.2pre25
+
+THISAPP    = spandsp-$(VER)
+DL_FILE    = $(THISAPP).tar.gz
+DL_FROM    = http://soft-switch.org/downloads/spandsp/spandsp-0.0.2pre25
+DIR_APP    = $(DIR_SRC)/spandsp-0.0.2
+TARGET     = $(DIR_INFO)/$(THISAPP)
+
+###############################################################################
+# Top-level Rules
+###############################################################################
+
+objects = $(DL_FILE)
+
+$(DL_FILE) = $(DL_FROM)/$(DL_FILE)
+
+$(DL_FILE)_MD5 = 2bbd518eec1ac0214d1d0f8abb6772a3
+
+install : $(TARGET)
+
+check : $(patsubst %,$(DIR_CHK)/%,$(objects))
+
+download :$(patsubst %,$(DIR_DL)/%,$(objects))
+
+md5 : $(subst %,%_MD5,$(objects))
+
+dist: 
+       make-packages.sh spandsp $(THISAPP)-ipfire-beta-1
+
+###############################################################################
+# Downloading, checking, md5sum
+###############################################################################
+
+$(patsubst %,$(DIR_CHK)/%,$(objects)) :
+       @$(CHECK)
+
+$(patsubst %,$(DIR_DL)/%,$(objects)) :
+       @$(LOAD)
+
+$(subst %,%_MD5,$(objects)) :
+       @$(MD5)
+
+###############################################################################
+# Installation Details
+###############################################################################
+
+$(TARGET) : $(patsubst %,$(DIR_DL)/%,$(objects))
+       @$(PREBUILD)
+       @rm -rf $(DIR_APP) && cd $(DIR_SRC) && tar zxf $(DIR_DL)/$(DL_FILE)
+       cd $(DIR_APP) && ./configure --prefix=/usr
+       cd $(DIR_APP) && make
+       cd $(DIR_APP) && make install
+       @rm -rf $(DIR_APP)
+       @$(POSTBUILD)
diff --git a/make.sh b/make.sh
index 5f47f1a..40b49da 100644 (file)
--- a/make.sh
+++ b/make.sh
@@ -647,32 +647,37 @@ buildipcop() {
   ipcopmake libsafe
   ipcopmake 3c5x9setup
   echo -ne "`date -u '+%b %e %T'`: Building IPFire modules \n" | tee -a $LOGFILE
-  ipcopmake sudo
-##ipcopmake stunnel # Ausgeschaltet, weil wir es doch nicht nutzen
-  ipcopmake xinetd
+## Zuerst die Libs und dann die Programme. Ordnung muss sein!
+  ipcopmake berkeley-DB
+  ipcopmake libtiff
+  ipcopmake libxml2
+  ipcopmake spandsp
+  ipcopmake lzo
   ipcopmake pkg-config
   ipcopmake glib
+  ipcopmake pam
+  ipcopmake pammysql
+  ipcopmake sudo
+  ipcopmake mc
+  ipcopmake pwlib
+  ipcopmake openh323
+  ipcopmake xinetd
   ipcopmake wget
-  ipcopmake berkeley-DB
   ipcopmake xampp
   ipcopmake bridge-utils
-  ipcopmake pam
-  ipcopmake pammysql
   ipcopmake saslauthd PASS=1
   ipcopmake openldap
   ipcopmake saslauthd PASS=2
   ipcopmake samba
-  ipcopmake mc
   ipcopmake postfix
   ipcopmake stund
   ipcopmake lpd
-  ipcopmake pwlib
-  ipcopmake openh323
+  ipcopmake openvpn
+  ipcopmake asterisk
+  ipcopmake edonkeyclc
 #  wget http://www.guzu.net/linux/hddtemp.db && mv hddtemp.db $BASEDIR/build/etc/hddtemp.db
 #  ipcopmake hddtemp
-  ipcopmake lzo
-  ipcopmake openvpn
-
+# ipcopmake stunnel # Ausgeschaltet, weil wir es doch nicht nutzen
 }
 
 buildinstaller() {
@@ -762,8 +767,11 @@ buildpackages() {
   cp $LFS/install/images/{*.iso,*.tgz} $BASEDIR >> $LOGFILE 2>&1
 
   # Build IPFire packages
+  ipfiredist libtiff
+  ipfiredist libxml2
   ipfiredist mc
   ipfiredist postfix
+  ipfiredist spandsp
   ipfiredist sudo
   ipfiredist xinetd
   # Cleanup
diff --git a/src/paks/asterisk/CONFFILES b/src/paks/asterisk/CONFFILES
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/src/paks/asterisk/ROOTFILES b/src/paks/asterisk/ROOTFILES
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/src/paks/asterisk/install.sh b/src/paks/asterisk/install.sh
new file mode 100644 (file)
index 0000000..3a9ce55
--- /dev/null
@@ -0,0 +1,11 @@
+#!/bin/bash
+#
+#################################################################
+#                                                               #
+# This file belongs to IPFire Firewall - GPLv2 - www.ipfire.org #
+#                                                               #
+#################################################################
+#
+# Extract the files
+tar xfz files.tgz -C /
+cp -f ROOTFILES /opt/pakfire/installed/ROOTFILES.$2
diff --git a/src/paks/asterisk/uninstall.sh b/src/paks/asterisk/uninstall.sh
new file mode 100644 (file)
index 0000000..ad61226
--- /dev/null
@@ -0,0 +1,10 @@
+#!/bin/bash
+#################################################################
+#                                                               #
+# This file belongs to IPFire Firewall - GPLv2 - www.ipfire.org #
+#                                                               #
+#################################################################
+#
+# Delete the files
+## Befehl fehlt noch
+rm -f /opt/pakfire/installed/ROOTFILES.$2
diff --git a/src/paks/edonkeyclc/CONFFILES b/src/paks/edonkeyclc/CONFFILES
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/src/paks/edonkeyclc/ROOTFILES b/src/paks/edonkeyclc/ROOTFILES
new file mode 100644 (file)
index 0000000..3714bb5
--- /dev/null
@@ -0,0 +1,9 @@
+usr/bin/edonkeyclc
+#usr/share/doc/edonkeyclc
+#usr/share/doc/edonkeyclc/ChangeLog
+#usr/share/doc/edonkeyclc/LISEZMOI
+#usr/share/doc/edonkeyclc/README
+#usr/share/doc/edonkeyclc/changelog.Debian.gz
+#usr/share/edonkeyclc
+#usr/share/edonkeyclc/contact.dat
+#usr/share/edonkeyclc/server.met
diff --git a/src/paks/edonkeyclc/install.sh b/src/paks/edonkeyclc/install.sh
new file mode 100644 (file)
index 0000000..3a9ce55
--- /dev/null
@@ -0,0 +1,11 @@
+#!/bin/bash
+#
+#################################################################
+#                                                               #
+# This file belongs to IPFire Firewall - GPLv2 - www.ipfire.org #
+#                                                               #
+#################################################################
+#
+# Extract the files
+tar xfz files.tgz -C /
+cp -f ROOTFILES /opt/pakfire/installed/ROOTFILES.$2
diff --git a/src/paks/edonkeyclc/uninstall.sh b/src/paks/edonkeyclc/uninstall.sh
new file mode 100644 (file)
index 0000000..ad61226
--- /dev/null
@@ -0,0 +1,10 @@
+#!/bin/bash
+#################################################################
+#                                                               #
+# This file belongs to IPFire Firewall - GPLv2 - www.ipfire.org #
+#                                                               #
+#################################################################
+#
+# Delete the files
+## Befehl fehlt noch
+rm -f /opt/pakfire/installed/ROOTFILES.$2
diff --git a/src/paks/libtiff/CONFFILES b/src/paks/libtiff/CONFFILES
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/src/paks/libtiff/ROOTFILES b/src/paks/libtiff/ROOTFILES
new file mode 100644 (file)
index 0000000..87ac9f8
--- /dev/null
@@ -0,0 +1,235 @@
+usr/bin/bmp2tiff
+usr/bin/fax2ps
+usr/bin/fax2tiff
+usr/bin/gif2tiff
+usr/bin/pal2rgb
+usr/bin/ppm2tiff
+usr/bin/ras2tiff
+usr/bin/raw2tiff
+usr/bin/rgb2ycbcr
+usr/bin/thumbnail
+usr/bin/tiff2bw
+usr/bin/tiff2pdf
+usr/bin/tiff2ps
+usr/bin/tiff2rgba
+usr/bin/tiffcmp
+usr/bin/tiffcp
+usr/bin/tiffdither
+usr/bin/tiffdump
+usr/bin/tiffinfo
+usr/bin/tiffmedian
+usr/bin/tiffset
+usr/bin/tiffsplit
+#usr/include/tiff.h
+#usr/include/tiffconf.h
+#usr/include/tiffio.h
+#usr/include/tiffio.hxx
+#usr/include/tiffvers.h
+usr/lib/libtiff.a
+usr/lib/libtiff.la
+usr/lib/libtiff.so
+usr/lib/libtiff.so.3
+usr/lib/libtiff.so.3.8.2
+usr/lib/libtiffxx.a
+usr/lib/libtiffxx.la
+usr/lib/libtiffxx.so
+usr/lib/libtiffxx.so.3
+usr/lib/libtiffxx.so.3.8.2
+#usr/share/doc/tiff-3.8.2
+#usr/share/doc/tiff-3.8.2/COPYRIGHT
+#usr/share/doc/tiff-3.8.2/ChangeLog
+#usr/share/doc/tiff-3.8.2/README
+#usr/share/doc/tiff-3.8.2/RELEASE-DATE
+#usr/share/doc/tiff-3.8.2/TODO
+#usr/share/doc/tiff-3.8.2/VERSION
+#usr/share/doc/tiff-3.8.2/html
+#usr/share/doc/tiff-3.8.2/html/TIFFTechNote2.html
+#usr/share/doc/tiff-3.8.2/html/addingtags.html
+#usr/share/doc/tiff-3.8.2/html/bugs.html
+#usr/share/doc/tiff-3.8.2/html/build.html
+#usr/share/doc/tiff-3.8.2/html/contrib.html
+#usr/share/doc/tiff-3.8.2/html/document.html
+#usr/share/doc/tiff-3.8.2/html/images
+#usr/share/doc/tiff-3.8.2/html/images.html
+#usr/share/doc/tiff-3.8.2/html/images/back.gif
+#usr/share/doc/tiff-3.8.2/html/images/bali.jpg
+#usr/share/doc/tiff-3.8.2/html/images/cat.gif
+#usr/share/doc/tiff-3.8.2/html/images/cover.jpg
+#usr/share/doc/tiff-3.8.2/html/images/cramps.gif
+#usr/share/doc/tiff-3.8.2/html/images/dave.gif
+#usr/share/doc/tiff-3.8.2/html/images/info.gif
+#usr/share/doc/tiff-3.8.2/html/images/jello.jpg
+#usr/share/doc/tiff-3.8.2/html/images/jim.gif
+#usr/share/doc/tiff-3.8.2/html/images/note.gif
+#usr/share/doc/tiff-3.8.2/html/images/oxford.gif
+#usr/share/doc/tiff-3.8.2/html/images/quad.jpg
+#usr/share/doc/tiff-3.8.2/html/images/ring.gif
+#usr/share/doc/tiff-3.8.2/html/images/smallliz.jpg
+#usr/share/doc/tiff-3.8.2/html/images/strike.gif
+#usr/share/doc/tiff-3.8.2/html/images/warning.gif
+#usr/share/doc/tiff-3.8.2/html/index.html
+#usr/share/doc/tiff-3.8.2/html/internals.html
+#usr/share/doc/tiff-3.8.2/html/intro.html
+#usr/share/doc/tiff-3.8.2/html/libtiff.html
+#usr/share/doc/tiff-3.8.2/html/man
+#usr/share/doc/tiff-3.8.2/html/man/TIFFClose.3tiff.html
+#usr/share/doc/tiff-3.8.2/html/man/TIFFDataWidth.3tiff.html
+#usr/share/doc/tiff-3.8.2/html/man/TIFFError.3tiff.html
+#usr/share/doc/tiff-3.8.2/html/man/TIFFFlush.3tiff.html
+#usr/share/doc/tiff-3.8.2/html/man/TIFFGetField.3tiff.html
+#usr/share/doc/tiff-3.8.2/html/man/TIFFOpen.3tiff.html
+#usr/share/doc/tiff-3.8.2/html/man/TIFFPrintDirectory.3tiff.html
+#usr/share/doc/tiff-3.8.2/html/man/TIFFRGBAImage.3tiff.html
+#usr/share/doc/tiff-3.8.2/html/man/TIFFReadDirectory.3tiff.html
+#usr/share/doc/tiff-3.8.2/html/man/TIFFReadEncodedStrip.3tiff.html
+#usr/share/doc/tiff-3.8.2/html/man/TIFFReadEncodedTile.3tiff.html
+#usr/share/doc/tiff-3.8.2/html/man/TIFFReadRGBAImage.3tiff.html
+#usr/share/doc/tiff-3.8.2/html/man/TIFFReadRGBAStrip.3tiff.html
+#usr/share/doc/tiff-3.8.2/html/man/TIFFReadRGBATile.3tiff.html
+#usr/share/doc/tiff-3.8.2/html/man/TIFFReadRawStrip.3tiff.html
+#usr/share/doc/tiff-3.8.2/html/man/TIFFReadRawTile.3tiff.html
+#usr/share/doc/tiff-3.8.2/html/man/TIFFReadScanline.3tiff.html
+#usr/share/doc/tiff-3.8.2/html/man/TIFFReadTile.3tiff.html
+#usr/share/doc/tiff-3.8.2/html/man/TIFFSetDirectory.3tiff.html
+#usr/share/doc/tiff-3.8.2/html/man/TIFFSetField.3tiff.html
+#usr/share/doc/tiff-3.8.2/html/man/TIFFWarning.3tiff.html
+#usr/share/doc/tiff-3.8.2/html/man/TIFFWriteDirectory.3tiff.html
+#usr/share/doc/tiff-3.8.2/html/man/TIFFWriteEncodedStrip.3tiff.html
+#usr/share/doc/tiff-3.8.2/html/man/TIFFWriteEncodedTile.3tiff.html
+#usr/share/doc/tiff-3.8.2/html/man/TIFFWriteRawStrip.3tiff.html
+#usr/share/doc/tiff-3.8.2/html/man/TIFFWriteRawTile.3tiff.html
+#usr/share/doc/tiff-3.8.2/html/man/TIFFWriteScanline.3tiff.html
+#usr/share/doc/tiff-3.8.2/html/man/TIFFWriteTile.3tiff.html
+#usr/share/doc/tiff-3.8.2/html/man/TIFFbuffer.3tiff.html
+#usr/share/doc/tiff-3.8.2/html/man/TIFFcodec.3tiff.html
+#usr/share/doc/tiff-3.8.2/html/man/TIFFcolor.3tiff.html
+#usr/share/doc/tiff-3.8.2/html/man/TIFFmemory.3tiff.html
+#usr/share/doc/tiff-3.8.2/html/man/TIFFquery.3tiff.html
+#usr/share/doc/tiff-3.8.2/html/man/TIFFsize.3tiff.html
+#usr/share/doc/tiff-3.8.2/html/man/TIFFstrip.3tiff.html
+#usr/share/doc/tiff-3.8.2/html/man/TIFFswab.3tiff.html
+#usr/share/doc/tiff-3.8.2/html/man/TIFFtile.3tiff.html
+#usr/share/doc/tiff-3.8.2/html/man/fax2ps.1.html
+#usr/share/doc/tiff-3.8.2/html/man/fax2tiff.1.html
+#usr/share/doc/tiff-3.8.2/html/man/gif2tiff.1.html
+#usr/share/doc/tiff-3.8.2/html/man/index.html
+#usr/share/doc/tiff-3.8.2/html/man/libtiff.3tiff.html
+#usr/share/doc/tiff-3.8.2/html/man/pal2rgb.1.html
+#usr/share/doc/tiff-3.8.2/html/man/ppm2tiff.1.html
+#usr/share/doc/tiff-3.8.2/html/man/ras2tiff.1.html
+#usr/share/doc/tiff-3.8.2/html/man/raw2tiff.1.html
+#usr/share/doc/tiff-3.8.2/html/man/rgb2ycbcr.1.html
+#usr/share/doc/tiff-3.8.2/html/man/sgi2tiff.1.html
+#usr/share/doc/tiff-3.8.2/html/man/thumbnail.1.html
+#usr/share/doc/tiff-3.8.2/html/man/tiff2bw.1.html
+#usr/share/doc/tiff-3.8.2/html/man/tiff2pdf.1.html
+#usr/share/doc/tiff-3.8.2/html/man/tiff2ps.1.html
+#usr/share/doc/tiff-3.8.2/html/man/tiff2rgba.1.html
+#usr/share/doc/tiff-3.8.2/html/man/tiffcmp.1.html
+#usr/share/doc/tiff-3.8.2/html/man/tiffcp.1.html
+#usr/share/doc/tiff-3.8.2/html/man/tiffdither.1.html
+#usr/share/doc/tiff-3.8.2/html/man/tiffdump.1.html
+#usr/share/doc/tiff-3.8.2/html/man/tiffgt.1.html
+#usr/share/doc/tiff-3.8.2/html/man/tiffinfo.1.html
+#usr/share/doc/tiff-3.8.2/html/man/tiffmedian.1.html
+#usr/share/doc/tiff-3.8.2/html/man/tiffset.1.html
+#usr/share/doc/tiff-3.8.2/html/man/tiffsplit.1.html
+#usr/share/doc/tiff-3.8.2/html/man/tiffsv.1.html
+#usr/share/doc/tiff-3.8.2/html/misc.html
+#usr/share/doc/tiff-3.8.2/html/support.html
+#usr/share/doc/tiff-3.8.2/html/tools.html
+#usr/share/doc/tiff-3.8.2/html/v3.4beta007.html
+#usr/share/doc/tiff-3.8.2/html/v3.4beta016.html
+#usr/share/doc/tiff-3.8.2/html/v3.4beta018.html
+#usr/share/doc/tiff-3.8.2/html/v3.4beta024.html
+#usr/share/doc/tiff-3.8.2/html/v3.4beta028.html
+#usr/share/doc/tiff-3.8.2/html/v3.4beta029.html
+#usr/share/doc/tiff-3.8.2/html/v3.4beta031.html
+#usr/share/doc/tiff-3.8.2/html/v3.4beta032.html
+#usr/share/doc/tiff-3.8.2/html/v3.4beta033.html
+#usr/share/doc/tiff-3.8.2/html/v3.4beta034.html
+#usr/share/doc/tiff-3.8.2/html/v3.4beta035.html
+#usr/share/doc/tiff-3.8.2/html/v3.4beta036.html
+#usr/share/doc/tiff-3.8.2/html/v3.5.1.html
+#usr/share/doc/tiff-3.8.2/html/v3.5.2.html
+#usr/share/doc/tiff-3.8.2/html/v3.5.3.html
+#usr/share/doc/tiff-3.8.2/html/v3.5.4.html
+#usr/share/doc/tiff-3.8.2/html/v3.5.5.html
+#usr/share/doc/tiff-3.8.2/html/v3.5.6-beta.html
+#usr/share/doc/tiff-3.8.2/html/v3.5.7.html
+#usr/share/doc/tiff-3.8.2/html/v3.6.0.html
+#usr/share/doc/tiff-3.8.2/html/v3.6.1.html
+#usr/share/doc/tiff-3.8.2/html/v3.7.0.html
+#usr/share/doc/tiff-3.8.2/html/v3.7.0alpha.html
+#usr/share/doc/tiff-3.8.2/html/v3.7.0beta.html
+#usr/share/doc/tiff-3.8.2/html/v3.7.0beta2.html
+#usr/share/doc/tiff-3.8.2/html/v3.7.1.html
+#usr/share/doc/tiff-3.8.2/html/v3.7.2.html
+#usr/share/doc/tiff-3.8.2/html/v3.7.3.html
+#usr/share/doc/tiff-3.8.2/html/v3.7.4.html
+#usr/share/doc/tiff-3.8.2/html/v3.8.0.html
+#usr/share/doc/tiff-3.8.2/html/v3.8.1.html
+#usr/share/doc/tiff-3.8.2/html/v3.8.2.html
+#usr/share/man/man1/bmp2tiff.1
+#usr/share/man/man1/fax2ps.1
+#usr/share/man/man1/fax2tiff.1
+#usr/share/man/man1/gif2tiff.1
+#usr/share/man/man1/pal2rgb.1
+#usr/share/man/man1/ppm2tiff.1
+#usr/share/man/man1/ras2tiff.1
+#usr/share/man/man1/raw2tiff.1
+#usr/share/man/man1/rgb2ycbcr.1
+#usr/share/man/man1/sgi2tiff.1
+#usr/share/man/man1/thumbnail.1
+#usr/share/man/man1/tiff2bw.1
+#usr/share/man/man1/tiff2pdf.1
+#usr/share/man/man1/tiff2ps.1
+#usr/share/man/man1/tiff2rgba.1
+#usr/share/man/man1/tiffcmp.1
+#usr/share/man/man1/tiffcp.1
+#usr/share/man/man1/tiffdither.1
+#usr/share/man/man1/tiffdump.1
+#usr/share/man/man1/tiffgt.1
+#usr/share/man/man1/tiffinfo.1
+#usr/share/man/man1/tiffmedian.1
+#usr/share/man/man1/tiffset.1
+#usr/share/man/man1/tiffsplit.1
+#usr/share/man/man1/tiffsv.1
+#usr/share/man/man3/TIFFClose.3tiff
+#usr/share/man/man3/TIFFDataWidth.3tiff
+#usr/share/man/man3/TIFFError.3tiff
+#usr/share/man/man3/TIFFFlush.3tiff
+#usr/share/man/man3/TIFFGetField.3tiff
+#usr/share/man/man3/TIFFOpen.3tiff
+#usr/share/man/man3/TIFFPrintDirectory.3tiff
+#usr/share/man/man3/TIFFRGBAImage.3tiff
+#usr/share/man/man3/TIFFReadDirectory.3tiff
+#usr/share/man/man3/TIFFReadEncodedStrip.3tiff
+#usr/share/man/man3/TIFFReadEncodedTile.3tiff
+#usr/share/man/man3/TIFFReadRGBAImage.3tiff
+#usr/share/man/man3/TIFFReadRGBAStrip.3tiff
+#usr/share/man/man3/TIFFReadRGBATile.3tiff
+#usr/share/man/man3/TIFFReadRawStrip.3tiff
+#usr/share/man/man3/TIFFReadRawTile.3tiff
+#usr/share/man/man3/TIFFReadScanline.3tiff
+#usr/share/man/man3/TIFFReadTile.3tiff
+#usr/share/man/man3/TIFFSetDirectory.3tiff
+#usr/share/man/man3/TIFFSetField.3tiff
+#usr/share/man/man3/TIFFWarning.3tiff
+#usr/share/man/man3/TIFFWriteDirectory.3tiff
+#usr/share/man/man3/TIFFWriteEncodedStrip.3tiff
+#usr/share/man/man3/TIFFWriteEncodedTile.3tiff
+#usr/share/man/man3/TIFFWriteRawStrip.3tiff
+#usr/share/man/man3/TIFFWriteRawTile.3tiff
+#usr/share/man/man3/TIFFWriteScanline.3tiff
+#usr/share/man/man3/TIFFWriteTile.3tiff
+#usr/share/man/man3/TIFFbuffer.3tiff
+#usr/share/man/man3/TIFFcodec.3tiff
+#usr/share/man/man3/TIFFcolor.3tiff
+#usr/share/man/man3/TIFFmemory.3tiff
+#usr/share/man/man3/TIFFquery.3tiff
+#usr/share/man/man3/TIFFsize.3tiff
+#usr/share/man/man3/TIFFstrip.3tiff
+#usr/share/man/man3/TIFFswab.3tiff
+#usr/share/man/man3/TIFFtile.3tiff
+#usr/share/man/man3/libtiff.3tiff
diff --git a/src/paks/libtiff/install.sh b/src/paks/libtiff/install.sh
new file mode 100644 (file)
index 0000000..3a9ce55
--- /dev/null
@@ -0,0 +1,11 @@
+#!/bin/bash
+#
+#################################################################
+#                                                               #
+# This file belongs to IPFire Firewall - GPLv2 - www.ipfire.org #
+#                                                               #
+#################################################################
+#
+# Extract the files
+tar xfz files.tgz -C /
+cp -f ROOTFILES /opt/pakfire/installed/ROOTFILES.$2
diff --git a/src/paks/libtiff/uninstall.sh b/src/paks/libtiff/uninstall.sh
new file mode 100644 (file)
index 0000000..ad61226
--- /dev/null
@@ -0,0 +1,10 @@
+#!/bin/bash
+#################################################################
+#                                                               #
+# This file belongs to IPFire Firewall - GPLv2 - www.ipfire.org #
+#                                                               #
+#################################################################
+#
+# Delete the files
+## Befehl fehlt noch
+rm -f /opt/pakfire/installed/ROOTFILES.$2
diff --git a/src/paks/libxml2/CONFFILES b/src/paks/libxml2/CONFFILES
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/src/paks/libxml2/ROOTFILES b/src/paks/libxml2/ROOTFILES
new file mode 100644 (file)
index 0000000..e9f76b0
--- /dev/null
@@ -0,0 +1,333 @@
+usr/bin/xml2-config
+usr/bin/xmlcatalog
+usr/bin/xmllint
+#usr/include/libxml2
+#usr/include/libxml2/libxml
+#usr/include/libxml2/libxml/DOCBparser.h
+#usr/include/libxml2/libxml/HTMLparser.h
+#usr/include/libxml2/libxml/HTMLtree.h
+#usr/include/libxml2/libxml/SAX.h
+#usr/include/libxml2/libxml/SAX2.h
+#usr/include/libxml2/libxml/c14n.h
+#usr/include/libxml2/libxml/catalog.h
+#usr/include/libxml2/libxml/chvalid.h
+#usr/include/libxml2/libxml/debugXML.h
+#usr/include/libxml2/libxml/dict.h
+#usr/include/libxml2/libxml/encoding.h
+#usr/include/libxml2/libxml/entities.h
+#usr/include/libxml2/libxml/globals.h
+#usr/include/libxml2/libxml/hash.h
+#usr/include/libxml2/libxml/list.h
+#usr/include/libxml2/libxml/nanoftp.h
+#usr/include/libxml2/libxml/nanohttp.h
+#usr/include/libxml2/libxml/parser.h
+#usr/include/libxml2/libxml/parserInternals.h
+#usr/include/libxml2/libxml/pattern.h
+#usr/include/libxml2/libxml/relaxng.h
+#usr/include/libxml2/libxml/schemasInternals.h
+#usr/include/libxml2/libxml/schematron.h
+#usr/include/libxml2/libxml/threads.h
+#usr/include/libxml2/libxml/tree.h
+#usr/include/libxml2/libxml/uri.h
+#usr/include/libxml2/libxml/valid.h
+#usr/include/libxml2/libxml/xinclude.h
+#usr/include/libxml2/libxml/xlink.h
+#usr/include/libxml2/libxml/xmlIO.h
+#usr/include/libxml2/libxml/xmlautomata.h
+#usr/include/libxml2/libxml/xmlerror.h
+#usr/include/libxml2/libxml/xmlexports.h
+#usr/include/libxml2/libxml/xmlmemory.h
+#usr/include/libxml2/libxml/xmlmodule.h
+#usr/include/libxml2/libxml/xmlreader.h
+#usr/include/libxml2/libxml/xmlregexp.h
+#usr/include/libxml2/libxml/xmlsave.h
+#usr/include/libxml2/libxml/xmlschemas.h
+#usr/include/libxml2/libxml/xmlschemastypes.h
+#usr/include/libxml2/libxml/xmlstring.h
+#usr/include/libxml2/libxml/xmlunicode.h
+#usr/include/libxml2/libxml/xmlversion.h
+#usr/include/libxml2/libxml/xmlwriter.h
+#usr/include/libxml2/libxml/xpath.h
+#usr/include/libxml2/libxml/xpathInternals.h
+#usr/include/libxml2/libxml/xpointer.h
+usr/lib/libxml2.a
+usr/lib/libxml2.la
+usr/lib/libxml2.so
+usr/lib/libxml2.so.2
+usr/lib/libxml2.so.2.6.22
+usr/lib/pkgconfig/libxml-2.0.pc
+usr/lib/python2.3/site-packages/drv_libxml2.py
+usr/lib/python2.3/site-packages/libxml2.py
+usr/lib/python2.3/site-packages/libxml2mod.a
+usr/lib/python2.3/site-packages/libxml2mod.la
+usr/lib/python2.3/site-packages/libxml2mod.so
+usr/lib/xml2Conf.sh
+#usr/share/aclocal/libxml.m4
+#usr/share/doc/libxml2-2.6.22
+#usr/share/doc/libxml2-2.6.22/Copyright
+#usr/share/doc/libxml2-2.6.22/examples
+#usr/share/doc/libxml2-2.6.22/examples/testHTML.c
+#usr/share/doc/libxml2-2.6.22/examples/testSAX.c
+#usr/share/doc/libxml2-2.6.22/examples/testXPath.c
+#usr/share/doc/libxml2-2.6.22/examples/xmllint.c
+#usr/share/doc/libxml2-2.6.22/html
+#usr/share/doc/libxml2-2.6.22/html/DOM.gif
+#usr/share/doc/libxml2-2.6.22/html/FAQ.html
+#usr/share/doc/libxml2-2.6.22/html/Libxml2-Logo-180x168.gif
+#usr/share/doc/libxml2-2.6.22/html/Libxml2-Logo-90x34.gif
+#usr/share/doc/libxml2-2.6.22/html/encoding.html
+#usr/share/doc/libxml2-2.6.22/html/examples.xml
+#usr/share/doc/libxml2-2.6.22/html/examples.xsl
+#usr/share/doc/libxml2-2.6.22/html/html
+#usr/share/doc/libxml2-2.6.22/html/html/book1.html
+#usr/share/doc/libxml2-2.6.22/html/html/home.png
+#usr/share/doc/libxml2-2.6.22/html/html/index.html
+#usr/share/doc/libxml2-2.6.22/html/html/left.png
+#usr/share/doc/libxml2-2.6.22/html/html/libxml-DOCBparser.html
+#usr/share/doc/libxml2-2.6.22/html/html/libxml-HTMLparser.html
+#usr/share/doc/libxml2-2.6.22/html/html/libxml-HTMLtree.html
+#usr/share/doc/libxml2-2.6.22/html/html/libxml-SAX.html
+#usr/share/doc/libxml2-2.6.22/html/html/libxml-SAX2.html
+#usr/share/doc/libxml2-2.6.22/html/html/libxml-c14n.html
+#usr/share/doc/libxml2-2.6.22/html/html/libxml-catalog.html
+#usr/share/doc/libxml2-2.6.22/html/html/libxml-chvalid.html
+#usr/share/doc/libxml2-2.6.22/html/html/libxml-debugXML.html
+#usr/share/doc/libxml2-2.6.22/html/html/libxml-dict.html
+#usr/share/doc/libxml2-2.6.22/html/html/libxml-encoding.html
+#usr/share/doc/libxml2-2.6.22/html/html/libxml-entities.html
+#usr/share/doc/libxml2-2.6.22/html/html/libxml-globals.html
+#usr/share/doc/libxml2-2.6.22/html/html/libxml-hash.html
+#usr/share/doc/libxml2-2.6.22/html/html/libxml-lib.html
+#usr/share/doc/libxml2-2.6.22/html/html/libxml-list.html
+#usr/share/doc/libxml2-2.6.22/html/html/libxml-nanoftp.html
+#usr/share/doc/libxml2-2.6.22/html/html/libxml-nanohttp.html
+#usr/share/doc/libxml2-2.6.22/html/html/libxml-parser.html
+#usr/share/doc/libxml2-2.6.22/html/html/libxml-parserInternals.html
+#usr/share/doc/libxml2-2.6.22/html/html/libxml-pattern.html
+#usr/share/doc/libxml2-2.6.22/html/html/libxml-relaxng.html
+#usr/share/doc/libxml2-2.6.22/html/html/libxml-schemasInternals.html
+#usr/share/doc/libxml2-2.6.22/html/html/libxml-schematron.html
+#usr/share/doc/libxml2-2.6.22/html/html/libxml-threads.html
+#usr/share/doc/libxml2-2.6.22/html/html/libxml-tree.html
+#usr/share/doc/libxml2-2.6.22/html/html/libxml-uri.html
+#usr/share/doc/libxml2-2.6.22/html/html/libxml-valid.html
+#usr/share/doc/libxml2-2.6.22/html/html/libxml-xinclude.html
+#usr/share/doc/libxml2-2.6.22/html/html/libxml-xlink.html
+#usr/share/doc/libxml2-2.6.22/html/html/libxml-xmlIO.html
+#usr/share/doc/libxml2-2.6.22/html/html/libxml-xmlautomata.html
+#usr/share/doc/libxml2-2.6.22/html/html/libxml-xmlerror.html
+#usr/share/doc/libxml2-2.6.22/html/html/libxml-xmlexports.html
+#usr/share/doc/libxml2-2.6.22/html/html/libxml-xmlmemory.html
+#usr/share/doc/libxml2-2.6.22/html/html/libxml-xmlmodule.html
+#usr/share/doc/libxml2-2.6.22/html/html/libxml-xmlreader.html
+#usr/share/doc/libxml2-2.6.22/html/html/libxml-xmlregexp.html
+#usr/share/doc/libxml2-2.6.22/html/html/libxml-xmlsave.html
+#usr/share/doc/libxml2-2.6.22/html/html/libxml-xmlschemas.html
+#usr/share/doc/libxml2-2.6.22/html/html/libxml-xmlschemastypes.html
+#usr/share/doc/libxml2-2.6.22/html/html/libxml-xmlstring.html
+#usr/share/doc/libxml2-2.6.22/html/html/libxml-xmlunicode.html
+#usr/share/doc/libxml2-2.6.22/html/html/libxml-xmlversion.html
+#usr/share/doc/libxml2-2.6.22/html/html/libxml-xmlwriter.html
+#usr/share/doc/libxml2-2.6.22/html/html/libxml-xpath.html
+#usr/share/doc/libxml2-2.6.22/html/html/libxml-xpathInternals.html
+#usr/share/doc/libxml2-2.6.22/html/html/libxml-xpointer.html
+#usr/share/doc/libxml2-2.6.22/html/html/right.png
+#usr/share/doc/libxml2-2.6.22/html/html/up.png
+#usr/share/doc/libxml2-2.6.22/html/io1.c
+#usr/share/doc/libxml2-2.6.22/html/io1.res
+#usr/share/doc/libxml2-2.6.22/html/io2.c
+#usr/share/doc/libxml2-2.6.22/html/io2.res
+#usr/share/doc/libxml2-2.6.22/html/libxml.gif
+#usr/share/doc/libxml2-2.6.22/html/parse1.c
+#usr/share/doc/libxml2-2.6.22/html/parse2.c
+#usr/share/doc/libxml2-2.6.22/html/parse3.c
+#usr/share/doc/libxml2-2.6.22/html/parse4.c
+#usr/share/doc/libxml2-2.6.22/html/reader1.c
+#usr/share/doc/libxml2-2.6.22/html/reader1.res
+#usr/share/doc/libxml2-2.6.22/html/reader2.c
+#usr/share/doc/libxml2-2.6.22/html/reader3.c
+#usr/share/doc/libxml2-2.6.22/html/reader3.res
+#usr/share/doc/libxml2-2.6.22/html/reader4.c
+#usr/share/doc/libxml2-2.6.22/html/reader4.res
+#usr/share/doc/libxml2-2.6.22/html/redhat.gif
+#usr/share/doc/libxml2-2.6.22/html/smallfootonly.gif
+#usr/share/doc/libxml2-2.6.22/html/structure.gif
+#usr/share/doc/libxml2-2.6.22/html/test1.xml
+#usr/share/doc/libxml2-2.6.22/html/test2.xml
+#usr/share/doc/libxml2-2.6.22/html/test3.xml
+#usr/share/doc/libxml2-2.6.22/html/testWriter.c
+#usr/share/doc/libxml2-2.6.22/html/tree1.c
+#usr/share/doc/libxml2-2.6.22/html/tree1.res
+#usr/share/doc/libxml2-2.6.22/html/tree2.c
+#usr/share/doc/libxml2-2.6.22/html/tree2.res
+#usr/share/doc/libxml2-2.6.22/html/tst.xml
+#usr/share/doc/libxml2-2.6.22/html/tutorial
+#usr/share/doc/libxml2-2.6.22/html/tutorial/apa.html
+#usr/share/doc/libxml2-2.6.22/html/tutorial/apb.html
+#usr/share/doc/libxml2-2.6.22/html/tutorial/apc.html
+#usr/share/doc/libxml2-2.6.22/html/tutorial/apd.html
+#usr/share/doc/libxml2-2.6.22/html/tutorial/ape.html
+#usr/share/doc/libxml2-2.6.22/html/tutorial/apf.html
+#usr/share/doc/libxml2-2.6.22/html/tutorial/apg.html
+#usr/share/doc/libxml2-2.6.22/html/tutorial/aph.html
+#usr/share/doc/libxml2-2.6.22/html/tutorial/api.html
+#usr/share/doc/libxml2-2.6.22/html/tutorial/ar01s02.html
+#usr/share/doc/libxml2-2.6.22/html/tutorial/ar01s03.html
+#usr/share/doc/libxml2-2.6.22/html/tutorial/ar01s04.html
+#usr/share/doc/libxml2-2.6.22/html/tutorial/ar01s05.html
+#usr/share/doc/libxml2-2.6.22/html/tutorial/ar01s06.html
+#usr/share/doc/libxml2-2.6.22/html/tutorial/ar01s07.html
+#usr/share/doc/libxml2-2.6.22/html/tutorial/ar01s08.html
+#usr/share/doc/libxml2-2.6.22/html/tutorial/ar01s09.html
+#usr/share/doc/libxml2-2.6.22/html/tutorial/images
+#usr/share/doc/libxml2-2.6.22/html/tutorial/images/blank.png
+#usr/share/doc/libxml2-2.6.22/html/tutorial/images/callouts
+#usr/share/doc/libxml2-2.6.22/html/tutorial/images/callouts/1.png
+#usr/share/doc/libxml2-2.6.22/html/tutorial/images/callouts/10.png
+#usr/share/doc/libxml2-2.6.22/html/tutorial/images/callouts/2.png
+#usr/share/doc/libxml2-2.6.22/html/tutorial/images/callouts/3.png
+#usr/share/doc/libxml2-2.6.22/html/tutorial/images/callouts/4.png
+#usr/share/doc/libxml2-2.6.22/html/tutorial/images/callouts/5.png
+#usr/share/doc/libxml2-2.6.22/html/tutorial/images/callouts/6.png
+#usr/share/doc/libxml2-2.6.22/html/tutorial/images/callouts/7.png
+#usr/share/doc/libxml2-2.6.22/html/tutorial/images/callouts/8.png
+#usr/share/doc/libxml2-2.6.22/html/tutorial/images/callouts/9.png
+#usr/share/doc/libxml2-2.6.22/html/tutorial/images/caution.png
+#usr/share/doc/libxml2-2.6.22/html/tutorial/images/draft.png
+#usr/share/doc/libxml2-2.6.22/html/tutorial/images/home.png
+#usr/share/doc/libxml2-2.6.22/html/tutorial/images/important.png
+#usr/share/doc/libxml2-2.6.22/html/tutorial/images/next.png
+#usr/share/doc/libxml2-2.6.22/html/tutorial/images/note.png
+#usr/share/doc/libxml2-2.6.22/html/tutorial/images/prev.png
+#usr/share/doc/libxml2-2.6.22/html/tutorial/images/tip.png
+#usr/share/doc/libxml2-2.6.22/html/tutorial/images/toc-blank.png
+#usr/share/doc/libxml2-2.6.22/html/tutorial/images/toc-minus.png
+#usr/share/doc/libxml2-2.6.22/html/tutorial/images/toc-plus.png
+#usr/share/doc/libxml2-2.6.22/html/tutorial/images/up.png
+#usr/share/doc/libxml2-2.6.22/html/tutorial/images/warning.png
+#usr/share/doc/libxml2-2.6.22/html/tutorial/includeaddattribute.c
+#usr/share/doc/libxml2-2.6.22/html/tutorial/includeaddkeyword.c
+#usr/share/doc/libxml2-2.6.22/html/tutorial/includeconvert.c
+#usr/share/doc/libxml2-2.6.22/html/tutorial/includegetattribute.c
+#usr/share/doc/libxml2-2.6.22/html/tutorial/includekeyword.c
+#usr/share/doc/libxml2-2.6.22/html/tutorial/includexpath.c
+#usr/share/doc/libxml2-2.6.22/html/tutorial/index.html
+#usr/share/doc/libxml2-2.6.22/html/tutorial/ix01.html
+#usr/share/doc/libxml2-2.6.22/html/tutorial/xmltutorial.pdf
+#usr/share/doc/libxml2-2.6.22/html/w3c.png
+#usr/share/doc/libxml2-2.6.22/html/writer.xml
+#usr/share/doc/libxml2-2.6.22/html/xml.html
+#usr/share/doc/libxml2-2.6.22/html/xpath1.c
+#usr/share/doc/libxml2-2.6.22/html/xpath1.res
+#usr/share/doc/libxml2-2.6.22/html/xpath2.c
+#usr/share/doc/libxml2-2.6.22/html/xpath2.res
+#usr/share/doc/libxml2-python-2.6.22
+#usr/share/doc/libxml2-python-2.6.22/TODO
+#usr/share/doc/libxml2-python-2.6.22/examples
+#usr/share/doc/libxml2-python-2.6.22/examples/attribs.py
+#usr/share/doc/libxml2-python-2.6.22/examples/build.py
+#usr/share/doc/libxml2-python-2.6.22/examples/ctxterror.py
+#usr/share/doc/libxml2-python-2.6.22/examples/cutnpaste.py
+#usr/share/doc/libxml2-python-2.6.22/examples/dtdvalid.py
+#usr/share/doc/libxml2-python-2.6.22/examples/error.py
+#usr/share/doc/libxml2-python-2.6.22/examples/inbuf.py
+#usr/share/doc/libxml2-python-2.6.22/examples/indexes.py
+#usr/share/doc/libxml2-python-2.6.22/examples/invalid.xml
+#usr/share/doc/libxml2-python-2.6.22/examples/nsdel.py
+#usr/share/doc/libxml2-python-2.6.22/examples/outbuf.py
+#usr/share/doc/libxml2-python-2.6.22/examples/push.py
+#usr/share/doc/libxml2-python-2.6.22/examples/pushSAX.py
+#usr/share/doc/libxml2-python-2.6.22/examples/pushSAXhtml.py
+#usr/share/doc/libxml2-python-2.6.22/examples/reader.py
+#usr/share/doc/libxml2-python-2.6.22/examples/reader2.py
+#usr/share/doc/libxml2-python-2.6.22/examples/reader3.py
+#usr/share/doc/libxml2-python-2.6.22/examples/reader4.py
+#usr/share/doc/libxml2-python-2.6.22/examples/reader5.py
+#usr/share/doc/libxml2-python-2.6.22/examples/reader6.py
+#usr/share/doc/libxml2-python-2.6.22/examples/reader7.py
+#usr/share/doc/libxml2-python-2.6.22/examples/reader8.py
+#usr/share/doc/libxml2-python-2.6.22/examples/readererr.py
+#usr/share/doc/libxml2-python-2.6.22/examples/readernext.py
+#usr/share/doc/libxml2-python-2.6.22/examples/regexp.py
+#usr/share/doc/libxml2-python-2.6.22/examples/relaxng.py
+#usr/share/doc/libxml2-python-2.6.22/examples/resolver.py
+#usr/share/doc/libxml2-python-2.6.22/examples/schema.py
+#usr/share/doc/libxml2-python-2.6.22/examples/serialize.py
+#usr/share/doc/libxml2-python-2.6.22/examples/sync.py
+#usr/share/doc/libxml2-python-2.6.22/examples/test.dtd
+#usr/share/doc/libxml2-python-2.6.22/examples/thread2.py
+#usr/share/doc/libxml2-python-2.6.22/examples/tst.py
+#usr/share/doc/libxml2-python-2.6.22/examples/tst.xml
+#usr/share/doc/libxml2-python-2.6.22/examples/tstLastError.py
+#usr/share/doc/libxml2-python-2.6.22/examples/tstURI.py
+#usr/share/doc/libxml2-python-2.6.22/examples/tstmem.py
+#usr/share/doc/libxml2-python-2.6.22/examples/tstxpath.py
+#usr/share/doc/libxml2-python-2.6.22/examples/valid.xml
+#usr/share/doc/libxml2-python-2.6.22/examples/validDTD.py
+#usr/share/doc/libxml2-python-2.6.22/examples/validRNG.py
+#usr/share/doc/libxml2-python-2.6.22/examples/validSchemas.py
+#usr/share/doc/libxml2-python-2.6.22/examples/validate.py
+#usr/share/doc/libxml2-python-2.6.22/examples/walker.py
+#usr/share/doc/libxml2-python-2.6.22/examples/xpath.py
+#usr/share/doc/libxml2-python-2.6.22/examples/xpathext.py
+#usr/share/doc/libxml2-python-2.6.22/examples/xpathret.py
+#usr/share/gtk-doc/html/libxml2
+#usr/share/gtk-doc/html/libxml2/general.html
+#usr/share/gtk-doc/html/libxml2/home.png
+#usr/share/gtk-doc/html/libxml2/index.html
+#usr/share/gtk-doc/html/libxml2/left.png
+#usr/share/gtk-doc/html/libxml2/libxml2-DOCBparser.html
+#usr/share/gtk-doc/html/libxml2/libxml2-HTMLparser.html
+#usr/share/gtk-doc/html/libxml2/libxml2-HTMLtree.html
+#usr/share/gtk-doc/html/libxml2/libxml2-SAX.html
+#usr/share/gtk-doc/html/libxml2/libxml2-SAX2.html
+#usr/share/gtk-doc/html/libxml2/libxml2-c14n.html
+#usr/share/gtk-doc/html/libxml2/libxml2-catalog.html
+#usr/share/gtk-doc/html/libxml2/libxml2-chvalid.html
+#usr/share/gtk-doc/html/libxml2/libxml2-debugXML.html
+#usr/share/gtk-doc/html/libxml2/libxml2-dict.html
+#usr/share/gtk-doc/html/libxml2/libxml2-encoding.html
+#usr/share/gtk-doc/html/libxml2/libxml2-entities.html
+#usr/share/gtk-doc/html/libxml2/libxml2-globals.html
+#usr/share/gtk-doc/html/libxml2/libxml2-hash.html
+#usr/share/gtk-doc/html/libxml2/libxml2-list.html
+#usr/share/gtk-doc/html/libxml2/libxml2-nanoftp.html
+#usr/share/gtk-doc/html/libxml2/libxml2-nanohttp.html
+#usr/share/gtk-doc/html/libxml2/libxml2-parser.html
+#usr/share/gtk-doc/html/libxml2/libxml2-parserInternals.html
+#usr/share/gtk-doc/html/libxml2/libxml2-pattern.html
+#usr/share/gtk-doc/html/libxml2/libxml2-relaxng.html
+#usr/share/gtk-doc/html/libxml2/libxml2-schemasInternals.html
+#usr/share/gtk-doc/html/libxml2/libxml2-schematron.html
+#usr/share/gtk-doc/html/libxml2/libxml2-threads.html
+#usr/share/gtk-doc/html/libxml2/libxml2-tree.html
+#usr/share/gtk-doc/html/libxml2/libxml2-uri.html
+#usr/share/gtk-doc/html/libxml2/libxml2-valid.html
+#usr/share/gtk-doc/html/libxml2/libxml2-xinclude.html
+#usr/share/gtk-doc/html/libxml2/libxml2-xlink.html
+#usr/share/gtk-doc/html/libxml2/libxml2-xmlIO.html
+#usr/share/gtk-doc/html/libxml2/libxml2-xmlautomata.html
+#usr/share/gtk-doc/html/libxml2/libxml2-xmlerror.html
+#usr/share/gtk-doc/html/libxml2/libxml2-xmlexports.html
+#usr/share/gtk-doc/html/libxml2/libxml2-xmlmemory.html
+#usr/share/gtk-doc/html/libxml2/libxml2-xmlmodule.html
+#usr/share/gtk-doc/html/libxml2/libxml2-xmlreader.html
+#usr/share/gtk-doc/html/libxml2/libxml2-xmlregexp.html
+#usr/share/gtk-doc/html/libxml2/libxml2-xmlsave.html
+#usr/share/gtk-doc/html/libxml2/libxml2-xmlschemas.html
+#usr/share/gtk-doc/html/libxml2/libxml2-xmlschemastypes.html
+#usr/share/gtk-doc/html/libxml2/libxml2-xmlstring.html
+#usr/share/gtk-doc/html/libxml2/libxml2-xmlunicode.html
+#usr/share/gtk-doc/html/libxml2/libxml2-xmlversion.html
+#usr/share/gtk-doc/html/libxml2/libxml2-xmlwriter.html
+#usr/share/gtk-doc/html/libxml2/libxml2-xpath.html
+#usr/share/gtk-doc/html/libxml2/libxml2-xpathInternals.html
+#usr/share/gtk-doc/html/libxml2/libxml2-xpointer.html
+#usr/share/gtk-doc/html/libxml2/libxml2.devhelp
+#usr/share/gtk-doc/html/libxml2/right.png
+#usr/share/gtk-doc/html/libxml2/style.css
+#usr/share/gtk-doc/html/libxml2/up.png
+#usr/share/man/man1/xml2-config.1
+#usr/share/man/man1/xmlcatalog.1
+#usr/share/man/man1/xmllint.1
+#usr/share/man/man3/libxml.3
diff --git a/src/paks/libxml2/install.sh b/src/paks/libxml2/install.sh
new file mode 100644 (file)
index 0000000..3a9ce55
--- /dev/null
@@ -0,0 +1,11 @@
+#!/bin/bash
+#
+#################################################################
+#                                                               #
+# This file belongs to IPFire Firewall - GPLv2 - www.ipfire.org #
+#                                                               #
+#################################################################
+#
+# Extract the files
+tar xfz files.tgz -C /
+cp -f ROOTFILES /opt/pakfire/installed/ROOTFILES.$2
diff --git a/src/paks/libxml2/uninstall.sh b/src/paks/libxml2/uninstall.sh
new file mode 100644 (file)
index 0000000..ad61226
--- /dev/null
@@ -0,0 +1,10 @@
+#!/bin/bash
+#################################################################
+#                                                               #
+# This file belongs to IPFire Firewall - GPLv2 - www.ipfire.org #
+#                                                               #
+#################################################################
+#
+# Delete the files
+## Befehl fehlt noch
+rm -f /opt/pakfire/installed/ROOTFILES.$2
diff --git a/src/paks/spandsp/CONFFILES b/src/paks/spandsp/CONFFILES
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/src/paks/spandsp/ROOTFILES b/src/paks/spandsp/ROOTFILES
new file mode 100644 (file)
index 0000000..4689120
--- /dev/null
@@ -0,0 +1,65 @@
+#usr/include/spandsp
+#usr/include/spandsp.h
+#usr/include/spandsp/adsi.h
+#usr/include/spandsp/alaw_ulaw.h
+#usr/include/spandsp/arctan2.h
+#usr/include/spandsp/async.h
+#usr/include/spandsp/awgn.h
+#usr/include/spandsp/bert.h
+#usr/include/spandsp/biquad.h
+#usr/include/spandsp/complex.h
+#usr/include/spandsp/complex_filters.h
+#usr/include/spandsp/dc_restore.h
+#usr/include/spandsp/dds.h
+#usr/include/spandsp/ec_disable_tone.h
+#usr/include/spandsp/echo.h
+#usr/include/spandsp/fir.h
+#usr/include/spandsp/fsk.h
+#usr/include/spandsp/g168models.h
+#usr/include/spandsp/g722.h
+#usr/include/spandsp/g726.h
+#usr/include/spandsp/hdlc.h
+#usr/include/spandsp/ima_adpcm.h
+#usr/include/spandsp/logging.h
+#usr/include/spandsp/mmx.h
+#usr/include/spandsp/modem_echo.h
+#usr/include/spandsp/noise.h
+#usr/include/spandsp/oki_adpcm.h
+#usr/include/spandsp/oss.h
+#usr/include/spandsp/playout.h
+#usr/include/spandsp/plc.h
+#usr/include/spandsp/power_meter.h
+#usr/include/spandsp/queue.h
+#usr/include/spandsp/schedule.h
+#usr/include/spandsp/sig_tone.h
+#usr/include/spandsp/super_tone_rx.h
+#usr/include/spandsp/super_tone_tx.h
+#usr/include/spandsp/t30.h
+#usr/include/spandsp/t30_fcf.h
+#usr/include/spandsp/t31.h
+#usr/include/spandsp/t35.h
+#usr/include/spandsp/t4.h
+#usr/include/spandsp/telephony.h
+#usr/include/spandsp/time_scale.h
+#usr/include/spandsp/timing.h
+#usr/include/spandsp/tone_detect.h
+#usr/include/spandsp/tone_generate.h
+#usr/include/spandsp/v17rx.h
+#usr/include/spandsp/v17tx.h
+#usr/include/spandsp/v22bis.h
+#usr/include/spandsp/v27ter_rx.h
+#usr/include/spandsp/v27ter_tx.h
+#usr/include/spandsp/v29rx.h
+#usr/include/spandsp/v29tx.h
+#usr/include/spandsp/v42.h
+#usr/include/spandsp/v42bis.h
+#usr/include/spandsp/v8.h
+#usr/include/spandsp/vector.h
+usr/lib/libspandsp.a
+usr/lib/libspandsp.la
+usr/lib/libspandsp.so
+usr/lib/libspandsp.so.0
+usr/lib/libspandsp.so.0.0.1
+usr/share/spandsp
+usr/share/spandsp/global-tones.xml
+usr/share/spandsp/tones.dtd
diff --git a/src/paks/spandsp/install.sh b/src/paks/spandsp/install.sh
new file mode 100644 (file)
index 0000000..3a9ce55
--- /dev/null
@@ -0,0 +1,11 @@
+#!/bin/bash
+#
+#################################################################
+#                                                               #
+# This file belongs to IPFire Firewall - GPLv2 - www.ipfire.org #
+#                                                               #
+#################################################################
+#
+# Extract the files
+tar xfz files.tgz -C /
+cp -f ROOTFILES /opt/pakfire/installed/ROOTFILES.$2
diff --git a/src/paks/spandsp/uninstall.sh b/src/paks/spandsp/uninstall.sh
new file mode 100644 (file)
index 0000000..ad61226
--- /dev/null
@@ -0,0 +1,10 @@
+#!/bin/bash
+#################################################################
+#                                                               #
+# This file belongs to IPFire Firewall - GPLv2 - www.ipfire.org #
+#                                                               #
+#################################################################
+#
+# Delete the files
+## Befehl fehlt noch
+rm -f /opt/pakfire/installed/ROOTFILES.$2
diff --git a/src/patches/asterisk-1.2.4-iax2-bristuff-0.3.0-PRE-1l.patch b/src/patches/asterisk-1.2.4-iax2-bristuff-0.3.0-PRE-1l.patch
new file mode 100644 (file)
index 0000000..5cbd642
--- /dev/null
@@ -0,0 +1,1828 @@
+diff -urN asterisk-1.2.4/channels/chan_iax2.c asterisk-1.2.4.carrier/channels/chan_iax2.c
+--- asterisk-1.2.4/channels/chan_iax2.c        2006-01-31 09:41:43.000000000 +0100
++++ asterisk-1.2.4.carrier/channels/chan_iax2.c        2006-02-08 09:49:45.000000000 +0100
+@@ -179,6 +179,8 @@
+ static struct ast_netsock_list *netsock;
+ static int defaultsockfd = -1;
++static char servername[80];
++
+ static int usecnt;
+ AST_MUTEX_DEFINE_STATIC(usecnt_lock);
+@@ -232,6 +234,10 @@
+ static pthread_t netthreadid = AST_PTHREADT_NULL;
++static pthread_t regthreadid = AST_PTHREADT_NULL;
++
++static pthread_t auththreadid = AST_PTHREADT_NULL;
++
+ enum {
+       IAX_STATE_STARTED =             (1 << 0),
+       IAX_STATE_AUTHENTICATED =       (1 << 1),
+@@ -606,6 +612,25 @@
+       ast_mutex_t lock;
+ } iaxq;
++typedef struct iax_auth_frame {
++      struct iax_auth_frame *prev;
++      struct iax_auth_frame *next;
++      struct iax_frame *frame;
++      struct sockaddr_in sin;
++      int fd;
++      int subclass;
++      struct iax_ies ies;
++      unsigned char iebuf[4096];
++} iax_auth_frame;
++
++static struct ast_iax2_auth_queue {
++      struct iax_auth_frame *head;
++      struct iax_auth_frame *tail;
++      int count;
++      ast_cond_t cond;
++      ast_mutex_t lock;
++} callq, regq;
++
+ static struct ast_user_list {
+       struct iax2_user *users;
+       ast_mutex_t lock;
+@@ -712,6 +737,8 @@
+ static struct chan_iax2_pvt *iaxs[IAX_MAX_CALLS];
+ static ast_mutex_t iaxsl[IAX_MAX_CALLS];
+ static struct timeval lastused[IAX_MAX_CALLS];
++/* some packets have been queued for asynchronous processing */
++static int iaxs_queued[IAX_MAX_CALLS];
+ static int send_command(struct chan_iax2_pvt *, char, int, unsigned int, const unsigned char *, int, int);
+@@ -798,11 +825,12 @@
+ static int send_lagrq(void *data)
+ {
+       int callno = (long)data;
+-      /* Ping only if it's real not if it's bridged */
++      /* Ping only if it's real not if it's bridged (and not if it's queued!)*/
+       if (iaxs[callno]) {
+ #ifdef BRIDGE_OPTIMIZATION
+               if (!iaxs[callno]->bridgecallno)
+ #endif                
++                  if (!iaxs_queued[callno])
+                       send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_LAGRQ, 0, NULL, 0, -1);
+               return 1;
+       } else
+@@ -1070,8 +1098,9 @@
+               }
+       }
+       if ((res < 1) && (new >= NEW_ALLOW)) {
+-              if (!iax2_getpeername(*sin, host, sizeof(host), lockpeer))
+-                      snprintf(host, sizeof(host), "%s:%d", ast_inet_ntoa(iabuf, sizeof(iabuf), sin->sin_addr), ntohs(sin->sin_port));
++              /* We are NOT calling iax2_getpeernme() here, because it WILL BLOCK when using realtime.
++                 Instead we will overwrite the host filed in the iax_pvt for each new call or registration. */
++              snprintf(host, sizeof(host), "%s:%d", ast_inet_ntoa(iabuf, sizeof(iabuf), sin->sin_addr), ntohs(sin->sin_port));
+               gettimeofday(&now, NULL);
+               for (x=1;x<TRUNK_CALL_START;x++) {
+                       /* Find first unused call number that hasn't been used in a while */
+@@ -1141,6 +1170,58 @@
+       return 0;
+ }
++static int iax2_queue_auth_frame(struct ast_iax2_auth_queue *authq, int subclass, struct iax_frame *ifr, unsigned char *buf, unsigned char *iebuf, int iebuflen, struct sockaddr_in *sin, int fd, int maydrop)
++{
++      struct iax_auth_frame *fr = NULL;
++      /* 
++          ok, we get here with the iaxsl[callno] still locked. 
++          in any case we have to unlock it before returning.
++      */
++      
++      if (!authq || !ifr || !ifr->callno) return 1;       
++    
++      fr = malloc(sizeof(struct iax_auth_frame));
++      if (!fr) {
++          ast_log(LOG_ERROR, "Unable to malloc!\n");
++          return 1;
++      }
++      memset(fr,0,sizeof(fr));
++      fr->next = NULL;
++      fr->prev = NULL;
++      fr->frame = ifr;
++      fr->subclass = subclass;
++      fr->fd = fd;
++      memcpy(fr->iebuf, iebuf, iebuflen);
++      if (iebuflen)
++          iax_parse_ies(&fr->ies, fr->iebuf, iebuflen);
++      memcpy(&fr->sin, sin, sizeof(struct sockaddr_in));
++      ast_mutex_lock(&authq->lock);
++      if (maydrop && (authq->count > 5000)) {
++          ast_mutex_unlock(&authq->lock);
++          ast_mutex_unlock(&iaxsl[ifr->callno]);
++          free(fr);
++          if (option_verbose > 5)
++              ast_log(LOG_WARNING, "Queue too long, not queueing frame.\n");
++          return -1;
++      }
++      if (!authq->head) {
++              /* Empty queue */
++              authq->head = fr;
++              authq->tail = fr;
++      } else {
++              /* Double link */
++              authq->tail->next = fr;
++              fr->prev = authq->tail;
++              authq->tail = fr;
++      }
++      iaxs_queued[ifr->callno]++;
++      authq->count++;
++      ast_mutex_unlock(&iaxsl[ifr->callno]);
++      ast_cond_signal(&authq->cond);
++      ast_mutex_unlock(&authq->lock);
++      return 0;
++}
++
+ static void destroy_firmware(struct iax_firmware *cur)
+ {
+       /* Close firmware */
+@@ -1713,8 +1794,10 @@
+                                               /* Transfer timeout */
+                                               send_command(iaxs[f->callno], AST_FRAME_IAX, IAX_COMMAND_TXREJ, 0, NULL, 0, -1);
+                                       } else if (f->final) {
+-                                              if (f->final) 
++                                              if (!iaxs_queued[f->callno]) {
++                                                  if (f->final) 
+                                                       iax2_destroy_nolock(f->callno);
++                                              }
+                                       } else {
+                                               if (iaxs[f->callno]->owner)
+                                                       ast_log(LOG_WARNING, "Max retries exceeded to host %s on %s (type = %d, subclass = %d, ts=%d, seqno=%d)\n", ast_inet_ntoa(iabuf, sizeof(iabuf), iaxs[f->callno]->addr.sin_addr),iaxs[f->callno]->owner->name , f->af.frametype, f->af.subclass, f->ts, f->oseqno);
+@@ -1729,12 +1812,14 @@
+                                                       if (iaxs[f->callno]->owner)
+                                                               iaxs[f->callno]->owner->hangupcause = AST_CAUSE_DESTINATION_OUT_OF_ORDER;
+                                               } else {
+-                                                      if (iaxs[f->callno]->reg) {
++                                                      if (!iaxs_queued[f->callno]) {
++                                                          if (iaxs[f->callno]->reg) {
+                                                               memset(&iaxs[f->callno]->reg->us, 0, sizeof(iaxs[f->callno]->reg->us));
+                                                               iaxs[f->callno]->reg->regstate = REG_STATE_TIMEOUT;
+                                                               iaxs[f->callno]->reg->refresh = IAX_DEFAULT_REG_EXPIRE;
++                                                          }
++                                                          iax2_destroy_nolock(f->callno);
+                                                       }
+-                                                      iax2_destroy_nolock(f->callno);
+                                               }
+                                       }
+@@ -2706,6 +2791,8 @@
+       snprintf(regseconds, sizeof(regseconds), "%d", (int)nowtime);
+       ast_inet_ntoa(ipaddr, sizeof(ipaddr), sin->sin_addr);
+       snprintf(port, sizeof(port), "%d", ntohs(sin->sin_port));
++//    the following line is commented out for compatibility
++//    ast_update_realtime("iaxpeers", "name", peername, "ipaddr", ipaddr, "port", port, "regseconds", regseconds, "servername", servername, NULL);
+       ast_update_realtime("iaxpeers", "name", peername, "ipaddr", ipaddr, "port", port, "regseconds", regseconds, NULL);
+ }
+@@ -5034,16 +5121,17 @@
+       }
+       /* We release the lock for the call to prevent a deadlock, but it's okay because
+          only the current thread could possibly make it go away or make changes */
+-      ast_mutex_unlock(&iaxsl[callno]);
++//    ast_mutex_unlock(&iaxsl[callno]);
+       /* SLD: first call to lookup peer during registration */
+       p = find_peer(peer, 1);
+-      ast_mutex_lock(&iaxsl[callno]);
+-
++//    ast_mutex_lock(&iaxsl[callno]);
+       if (!p) {
+               if (authdebug)
+                       ast_log(LOG_NOTICE, "No registration for peer '%s' (from %s)\n", peer, ast_inet_ntoa(iabuf, sizeof(iabuf), sin->sin_addr));
+               return -1;
+       }
++      /* set the host name here. instead of doing it in find_callno() */
++      ast_copy_string(iaxs[callno]->host, p->name, sizeof(iaxs[callno]->host));
+       if (!ast_test_flag(p, IAX_DYNAMIC)) {
+               if (authdebug)
+@@ -5677,11 +5765,13 @@
+       if (!refresh)
+               refresh = min_reg_expire;
+       if (refresh > max_reg_expire) {
+-              ast_log(LOG_NOTICE, "Restricting registration for peer '%s' to %d seconds (requested %d)\n",
++              if (option_verbose > 5)
++                  ast_log(LOG_NOTICE, "Restricting registration for peer '%s' to %d seconds (requested %d)\n",
+                       p->name, max_reg_expire, refresh);
+               p->expiry = max_reg_expire;
+       } else if (refresh < min_reg_expire) {
+-              ast_log(LOG_NOTICE, "Restricting registration for peer '%s' to %d seconds (requested %d)\n",
++              if (option_verbose > 5)
++                  ast_log(LOG_NOTICE, "Restricting registration for peer '%s' to %d seconds (requested %d)\n",
+                       p->name, min_reg_expire, refresh);
+               p->expiry = min_reg_expire;
+       } else {
+@@ -5720,6 +5810,7 @@
+               iax_ie_append_short(&ied, IAX_IE_FIRMWAREVER, version);
+       if (ast_test_flag(p, IAX_TEMPONLY))
+               destroy_peer(p);
++      ast_mutex_lock(&iaxsl[callno]);
+       return send_command_final(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_REGACK, 0, ied.buf, ied.pos, -1);
+ }
+@@ -6279,6 +6370,8 @@
+       struct timeval rxtrunktime;
+       struct iax_ies ies;
+       struct iax_ie_data ied0, ied1;
++      unsigned char iebuf[4096]; 
++      int iebuflen = 0;
+       int format;
+       int exists;
+       int minivid = 0;
+@@ -6609,9 +6702,11 @@
+                                                       cur->retries = -1;
+                                                       /* Destroy call if this is the end */
+                                                       if (cur->final) { 
+-                                                              if (iaxdebug && option_debug)
++                                                              if (!iaxs_queued[fr.callno]) {
++                                                                  if (iaxdebug && option_debug)
+                                                                       ast_log(LOG_DEBUG, "Really destroying %d, having been acked on final message\n", fr.callno);
+-                                                              iax2_destroy_nolock(fr.callno);
++                                                                  iax2_destroy_nolock(fr.callno);
++                                                              }
+                                                       }
+                                               }
+                                       }
+@@ -6639,6 +6734,8 @@
+               if (f.datalen) {
+                       if (f.frametype == AST_FRAME_IAX) {
++                              memcpy(iebuf, buf + sizeof(struct ast_iax2_full_hdr), f.datalen);
++                              iebuflen = f.datalen;
+                               if (iax_parse_ies(&ies, buf + sizeof(struct ast_iax2_full_hdr), f.datalen)) {
+                                       ast_log(LOG_WARNING, "Undecodable frame received from '%s'\n", ast_inet_ntoa(iabuf, sizeof(iabuf), sin.sin_addr));
+                                       ast_mutex_unlock(&iaxsl[fr.callno]);
+@@ -6772,166 +6869,11 @@
+                                       break;
+                               if (ies.provverpres && ies.serviceident && sin.sin_addr.s_addr)
+                                       check_provisioning(&sin, fd, ies.serviceident, ies.provver);
+-                              /* If we're in trunk mode, do it now, and update the trunk number in our frame before continuing */
+-                              if (ast_test_flag(iaxs[fr.callno], IAX_TRUNK)) {
+-                                      fr.callno = make_trunk(fr.callno, 1);
+-                              }
+                               /* For security, always ack immediately */
+                               if (delayreject)
+                                       send_command_immediate(iaxs[fr.callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr.ts, NULL, 0,fr.iseqno);
+-                              if (check_access(fr.callno, &sin, &ies)) {
+-                                      /* They're not allowed on */
+-                                      auth_fail(fr.callno, IAX_COMMAND_REJECT);
+-                                      if (authdebug)
+-                                              ast_log(LOG_NOTICE, "Rejected connect attempt from %s, who was trying to reach '%s@%s'\n", ast_inet_ntoa(iabuf, sizeof(iabuf), sin.sin_addr), iaxs[fr.callno]->exten, iaxs[fr.callno]->context);
+-                                      break;
+-                              }
+-                              /* This might re-enter the IAX code and need the lock */
+-                              if (strcasecmp(iaxs[fr.callno]->exten, "TBD")) {
+-                                      ast_mutex_unlock(&iaxsl[fr.callno]);
+-                                      exists = ast_exists_extension(NULL, iaxs[fr.callno]->context, iaxs[fr.callno]->exten, 1, iaxs[fr.callno]->cid_num);
+-                                      ast_mutex_lock(&iaxsl[fr.callno]);
+-                              } else
+-                                      exists = 0;
+-                              if (ast_strlen_zero(iaxs[fr.callno]->secret) && ast_strlen_zero(iaxs[fr.callno]->inkeys)) {
+-                                      if (strcmp(iaxs[fr.callno]->exten, "TBD") && !exists) {
+-                                              memset(&ied0, 0, sizeof(ied0));
+-                                              iax_ie_append_str(&ied0, IAX_IE_CAUSE, "No such context/extension");
+-                                              iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_NO_ROUTE_DESTINATION);
+-                                              send_command_final(iaxs[fr.callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1);
+-                                              if (authdebug)
+-                                                      ast_log(LOG_NOTICE, "Rejected connect attempt from %s, request '%s@%s' does not exist\n", ast_inet_ntoa(iabuf, sizeof(iabuf), sin.sin_addr), iaxs[fr.callno]->exten, iaxs[fr.callno]->context);
+-                                      } else {
+-                                              /* Select an appropriate format */
+-
+-                                              if(ast_test_flag(iaxs[fr.callno], IAX_CODEC_NOPREFS)) {
+-                                                      if(ast_test_flag(iaxs[fr.callno], IAX_CODEC_NOCAP)) {
+-                                                              using_prefs = "reqonly";
+-                                                      } else {
+-                                                              using_prefs = "disabled";
+-                                                      }
+-                                                      format = iaxs[fr.callno]->peerformat & iaxs[fr.callno]->capability;
+-                                                      memset(&pref, 0, sizeof(pref));
+-                                                      strcpy(caller_pref_buf, "disabled");
+-                                                      strcpy(host_pref_buf, "disabled");
+-                                              } else {
+-                                                      using_prefs = "mine";
+-                                                      if(ies.codec_prefs) {
+-                                                              ast_codec_pref_convert(&rpref, ies.codec_prefs, 32, 0);
+-                                                              /* If we are codec_first_choice we let the caller have the 1st shot at picking the codec.*/
+-                                                              if (ast_test_flag(iaxs[fr.callno], IAX_CODEC_USER_FIRST)) {
+-                                                                      pref = rpref;
+-                                                                      using_prefs = "caller";
+-                                                              } else {
+-                                                                      pref = iaxs[fr.callno]->prefs;
+-                                                              }
+-                                                      } else
+-                                                              pref = iaxs[fr.callno]->prefs;
+-                                              
+-                                                      format = ast_codec_choose(&pref, iaxs[fr.callno]->capability & iaxs[fr.callno]->peercapability, 0);
+-                                                      ast_codec_pref_string(&rpref, caller_pref_buf, sizeof(caller_pref_buf) - 1);
+-                                                      ast_codec_pref_string(&iaxs[fr.callno]->prefs, host_pref_buf, sizeof(host_pref_buf) - 1);
+-                                              }
+-                                              if (!format) {
+-                                                      if(!ast_test_flag(iaxs[fr.callno], IAX_CODEC_NOCAP))
+-                                                              format = iaxs[fr.callno]->peercapability & iaxs[fr.callno]->capability;
+-                                                      if (!format) {
+-                                                              memset(&ied0, 0, sizeof(ied0));
+-                                                              iax_ie_append_str(&ied0, IAX_IE_CAUSE, "Unable to negotiate codec");
+-                                                              iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL);
+-                                                              send_command_final(iaxs[fr.callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1);
+-                                                              if (authdebug) {
+-                                                                      if(ast_test_flag(iaxs[fr.callno], IAX_CODEC_NOCAP))
+-                                                                              ast_log(LOG_NOTICE, "Rejected connect attempt from %s, requested 0x%x incompatible with our capability 0x%x.\n", ast_inet_ntoa(iabuf, sizeof(iabuf), sin.sin_addr), iaxs[fr.callno]->peerformat, iaxs[fr.callno]->capability);
+-                                                                      else 
+-                                                                              ast_log(LOG_NOTICE, "Rejected connect attempt from %s, requested/capability 0x%x/0x%x incompatible with our capability 0x%x.\n", ast_inet_ntoa(iabuf, sizeof(iabuf), sin.sin_addr), iaxs[fr.callno]->peerformat, iaxs[fr.callno]->peercapability, iaxs[fr.callno]->capability);
+-                                                              }
+-                                                      } else {
+-                                                              /* Pick one... */
+-                                                              if(ast_test_flag(iaxs[fr.callno], IAX_CODEC_NOCAP)) {
+-                                                                      if(!(iaxs[fr.callno]->peerformat & iaxs[fr.callno]->capability))
+-                                                                              format = 0;
+-                                                              } else {
+-                                                                      if(ast_test_flag(iaxs[fr.callno], IAX_CODEC_NOPREFS)) {
+-                                                                              using_prefs = ast_test_flag(iaxs[fr.callno], IAX_CODEC_NOCAP) ? "reqonly" : "disabled";
+-                                                                              memset(&pref, 0, sizeof(pref));
+-                                                                              format = ast_best_codec(iaxs[fr.callno]->peercapability & iaxs[fr.callno]->capability);
+-                                                                              strcpy(caller_pref_buf,"disabled");
+-                                                                              strcpy(host_pref_buf,"disabled");
+-                                                                      } else {
+-                                                                              using_prefs = "mine";
+-                                                                              if(ies.codec_prefs) {
+-                                                                                      /* Do the opposite of what we tried above. */
+-                                                                                      if (ast_test_flag(iaxs[fr.callno], IAX_CODEC_USER_FIRST)) {
+-                                                                                              pref = iaxs[fr.callno]->prefs;                                                          
+-                                                                                      } else {
+-                                                                                              pref = rpref;
+-                                                                                              using_prefs = "caller";
+-                                                                                      }
+-                                                                                      format = ast_codec_choose(&pref, iaxs[fr.callno]->peercapability & iaxs[fr.callno]->capability, 1);
+-                                                                      
+-                                                                              } else /* if no codec_prefs IE do it the old way */
+-                                                                                      format = ast_best_codec(iaxs[fr.callno]->peercapability & iaxs[fr.callno]->capability); 
+-                                                                      }
+-                                                              }
+-
+-                                                              if (!format) {
+-                                                                      memset(&ied0, 0, sizeof(ied0));
+-                                                                      iax_ie_append_str(&ied0, IAX_IE_CAUSE, "Unable to negotiate codec");
+-                                                                      iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL);
+-                                                                      ast_log(LOG_ERROR, "No best format in 0x%x???\n", iaxs[fr.callno]->peercapability & iaxs[fr.callno]->capability);
+-                                                                      send_command_final(iaxs[fr.callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1);
+-                                                                      if (authdebug)
+-                                                                              ast_log(LOG_NOTICE, "Rejected connect attempt from %s, requested/capability 0x%x/0x%x incompatible with our capability 0x%x.\n", ast_inet_ntoa(iabuf, sizeof(iabuf), sin.sin_addr), iaxs[fr.callno]->peerformat, iaxs[fr.callno]->peercapability, iaxs[fr.callno]->capability);
+-                                                                      ast_set_flag(iaxs[fr.callno], IAX_ALREADYGONE); 
+-                                                                      break;
+-                                                              }
+-                                                      }
+-                                              }
+-                                              if (format) {
+-                                                      /* No authentication required, let them in */
+-                                                      memset(&ied1, 0, sizeof(ied1));
+-                                                      iax_ie_append_int(&ied1, IAX_IE_FORMAT, format);
+-                                                      send_command(iaxs[fr.callno], AST_FRAME_IAX, IAX_COMMAND_ACCEPT, 0, ied1.buf, ied1.pos, -1);
+-                                                      if (strcmp(iaxs[fr.callno]->exten, "TBD")) {
+-                                                              ast_set_flag(&iaxs[fr.callno]->state, IAX_STATE_STARTED);
+-                                                              if (option_verbose > 2) 
+-                                                                      ast_verbose(VERBOSE_PREFIX_3 "Accepting UNAUTHENTICATED call from %s:\n"
+-                                                                                              "%srequested format = %s,\n"
+-                                                                                              "%srequested prefs = %s,\n"
+-                                                                                              "%sactual format = %s,\n"
+-                                                                                              "%shost prefs = %s,\n"
+-                                                                                              "%spriority = %s\n",
+-                                                                                              ast_inet_ntoa(iabuf, sizeof(iabuf), sin.sin_addr), 
+-                                                                                              VERBOSE_PREFIX_4,
+-                                                                                              ast_getformatname(iaxs[fr.callno]->peerformat), 
+-                                                                                              VERBOSE_PREFIX_4,
+-                                                                                              caller_pref_buf,
+-                                                                                              VERBOSE_PREFIX_4,
+-                                                                                              ast_getformatname(format), 
+-                                                                                              VERBOSE_PREFIX_4,
+-                                                                                              host_pref_buf, 
+-                                                                                              VERBOSE_PREFIX_4,
+-                                                                                              using_prefs);
+-                                                              
+-                                                              if(!(c = ast_iax2_new(fr.callno, AST_STATE_RING, format)))
+-                                                                      iax2_destroy_nolock(fr.callno);
+-                                                      } else {
+-                                                              ast_set_flag(&iaxs[fr.callno]->state, IAX_STATE_TBD);
+-                                                              /* If this is a TBD call, we're ready but now what...  */
+-                                                              if (option_verbose > 2)
+-                                                                      ast_verbose(VERBOSE_PREFIX_3 "Accepted unauthenticated TBD call from %s\n", ast_inet_ntoa(iabuf, sizeof(iabuf), sin.sin_addr));
+-                                                      }
+-                                              }
+-                                      }
+-                                      break;
+-                              }
+-                              if (iaxs[fr.callno]->authmethods & IAX_AUTH_MD5)
+-                                      merge_encryption(iaxs[fr.callno],ies.encmethods);
+-                              else
+-                                      iaxs[fr.callno]->encmethods = 0;
+-                              authenticate_request(iaxs[fr.callno]);
+-                              ast_set_flag(&iaxs[fr.callno]->state, IAX_STATE_AUTHENTICATED);
++                              fr.af.datalen = 0;
++                              iax2_queue_auth_frame(&callq, f.subclass, iaxfrdup2(&fr), buf, iebuf, iebuflen, &sin, fd, 0);
+                               break;
+                       case IAX_COMMAND_DPREQ:
+                               /* Request status in the dialplan */
+@@ -6947,14 +6889,22 @@
+                               }
+                               break;
+                       case IAX_COMMAND_HANGUP:
+-                              ast_set_flag(iaxs[fr.callno], IAX_ALREADYGONE);
+-                              ast_log(LOG_DEBUG, "Immediately destroying %d, having received hangup\n", fr.callno);
+-                              /* Set hangup cause according to remote */
+-                              if (ies.causecode && iaxs[fr.callno]->owner)
+-                                      iaxs[fr.callno]->owner->hangupcause = ies.causecode;
+-                              /* Send ack immediately, before we destroy */
+-                              send_command_immediate(iaxs[fr.callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr.ts, NULL, 0,fr.iseqno);
+-                              iax2_destroy_nolock(fr.callno);
++                              if (iaxs_queued[fr.callno]) {
++                                  /* there is something queued, maybe the call has not been authorized yet. */
++                                  /* Send ack immediately, before we destroy */
++                                  send_command_immediate(iaxs[fr.callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr.ts, NULL, 0,fr.iseqno);
++                                  fr.af.datalen = 0;
++                                  iax2_queue_auth_frame(&callq, f.subclass, iaxfrdup2(&fr), buf, iebuf, iebuflen, &sin, fd, 0);
++                              } else {
++                                  ast_set_flag(iaxs[fr.callno], IAX_ALREADYGONE);
++                                  ast_log(LOG_DEBUG, "Immediately destroying %d, having received hangup\n", fr.callno);
++                                  /* Set hangup cause according to remote */
++                                  if (ies.causecode && iaxs[fr.callno]->owner)
++                                          iaxs[fr.callno]->owner->hangupcause = ies.causecode;
++                                  /* Send ack immediately, before we destroy */
++                                  send_command_immediate(iaxs[fr.callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr.ts, NULL, 0,fr.iseqno);
++                                  iax2_destroy_nolock(fr.callno);
++                              }
+                               break;
+                       case IAX_COMMAND_REJECT:
+                               memset(&f, 0, sizeof(f));
+@@ -7183,31 +7133,36 @@
+                               /* For security, always ack immediately */
+                               if (delayreject)
+                                       send_command_immediate(iaxs[fr.callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr.ts, NULL, 0,fr.iseqno);
+-                              /* Ignore once we've started */
+-                              if (ast_test_flag(&iaxs[fr.callno]->state, IAX_STATE_STARTED | IAX_STATE_TBD)) {
++                              if (iaxs_queued[fr.callno]) {
++                                  /* there is something queued, take the same path  */
++                                  fr.af.datalen = 0;
++                                  iax2_queue_auth_frame(&callq, f.subclass, iaxfrdup2(&fr), buf, iebuf, iebuflen, &sin, fd, 0);
++                              } else {
++                                  /* Ignore once we've started */
++                                  if (ast_test_flag(&iaxs[fr.callno]->state, IAX_STATE_STARTED | IAX_STATE_TBD)) {
+                                       ast_log(LOG_WARNING, "Call on %s is already up, can't start on it\n", iaxs[fr.callno]->owner ? iaxs[fr.callno]->owner->name : "<Unknown>");
+                                       break;
+-                              }
+-                              if (authenticate_verify(iaxs[fr.callno], &ies)) {
++                                  }
++                                  if (authenticate_verify(iaxs[fr.callno], &ies)) {
+                                       if (authdebug)
+                                               ast_log(LOG_NOTICE, "Host %s failed to authenticate as %s\n", ast_inet_ntoa(iabuf, sizeof(iabuf), iaxs[fr.callno]->addr.sin_addr), iaxs[fr.callno]->username);
+                                       memset(&ied0, 0, sizeof(ied0));
+                                       auth_fail(fr.callno, IAX_COMMAND_REJECT);
+                                       break;
+-                              }
+-                              if (strcasecmp(iaxs[fr.callno]->exten, "TBD")) {
++                                  }
++                                  if (strcasecmp(iaxs[fr.callno]->exten, "TBD")) {
+                                       /* This might re-enter the IAX code and need the lock */
+                                       exists = ast_exists_extension(NULL, iaxs[fr.callno]->context, iaxs[fr.callno]->exten, 1, iaxs[fr.callno]->cid_num);
+-                              } else
++                                  } else
+                                       exists = 0;
+-                              if (strcmp(iaxs[fr.callno]->exten, "TBD") && !exists) {
++                                  if (strcmp(iaxs[fr.callno]->exten, "TBD") && !exists) {
+                                       if (authdebug)
+                                               ast_log(LOG_NOTICE, "Rejected connect attempt from %s, request '%s@%s' does not exist\n", ast_inet_ntoa(iabuf, sizeof(iabuf), sin.sin_addr), iaxs[fr.callno]->exten, iaxs[fr.callno]->context);
+                                       memset(&ied0, 0, sizeof(ied0));
+                                       iax_ie_append_str(&ied0, IAX_IE_CAUSE, "No such context/extension");
+                                       iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_NO_ROUTE_DESTINATION);
+                                       send_command_final(iaxs[fr.callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1);
+-                              } else {
++                                  } else {
+                                       /* Select an appropriate format */
+                                       if(ast_test_flag(iaxs[fr.callno], IAX_CODEC_NOPREFS)) {
+                                               if(ast_test_flag(iaxs[fr.callno], IAX_CODEC_NOCAP)) {
+@@ -7332,6 +7287,7 @@
+                                                               ast_verbose(VERBOSE_PREFIX_3 "Accepted AUTHENTICATED TBD call from %s\n", ast_inet_ntoa(iabuf, sizeof(iabuf), sin.sin_addr));
+                                               }
+                                       }
++                                  }
+                               }
+                               break;
+                       case IAX_COMMAND_DIAL:
+@@ -7357,11 +7313,16 @@
+                               }
+                               break;
+                       case IAX_COMMAND_INVAL:
+-                              iaxs[fr.callno]->error = ENOTCONN;
+-                              ast_log(LOG_DEBUG, "Immediately destroying %d, having received INVAL\n", fr.callno);
+-                              iax2_destroy_nolock(fr.callno);
+-                              if (option_debug)
++                              if (iaxs_queued[fr.callno]) {
++                                  fr.af.datalen = 0;
++                                  iax2_queue_auth_frame(&callq, f.subclass, iaxfrdup2(&fr), buf, iebuf, iebuflen, &sin, fd, 0);
++                              } else {
++                                  iaxs[fr.callno]->error = ENOTCONN;
++                                  ast_log(LOG_DEBUG, "Immediately destroying %d, having received INVAL\n", fr.callno);
++                                  iax2_destroy_nolock(fr.callno);
++                                  if (option_debug)
+                                       ast_log(LOG_DEBUG, "Destroying call %d\n", fr.callno);
++                              }
+                               break;
+                       case IAX_COMMAND_VNAK:
+                               ast_log(LOG_DEBUG, "Received VNAK: resending outstanding frames\n");
+@@ -7373,21 +7334,11 @@
+                               /* For security, always ack immediately */
+                               if (delayreject)
+                                       send_command_immediate(iaxs[fr.callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr.ts, NULL, 0,fr.iseqno);
+-                              if (register_verify(fr.callno, &sin, &ies)) {
+-                                      /* Send delayed failure */
+-                                      auth_fail(fr.callno, IAX_COMMAND_REGREJ);
+-                                      break;
+-                              }
+-                              if ((ast_strlen_zero(iaxs[fr.callno]->secret) && ast_strlen_zero(iaxs[fr.callno]->inkeys)) || ast_test_flag(&iaxs[fr.callno]->state, IAX_STATE_AUTHENTICATED)) {
+-                                      if (f.subclass == IAX_COMMAND_REGREL)
+-                                              memset(&sin, 0, sizeof(sin));
+-                                      if (update_registry(iaxs[fr.callno]->peer, &sin, fr.callno, ies.devicetype, fd, ies.refresh))
+-                                              ast_log(LOG_WARNING, "Registry error\n");
+-                                      if (ies.provverpres && ies.serviceident && sin.sin_addr.s_addr)
+-                                              check_provisioning(&sin, fd, ies.serviceident, ies.provver);
+-                                      break;
++                              fr.af.datalen = 0;
++                              if (iax2_queue_auth_frame(&regq, f.subclass, iaxfrdup2(&fr), buf, iebuf, iebuflen, &sin, fd, 1)) {
++                                  /* queueing failed due to a full queue */
++                                  iax2_destroy_nolock(fr.callno);
+                               }
+-                              registry_authrequest(iaxs[fr.callno]->peer, fr.callno);
+                               break;
+                       case IAX_COMMAND_REGACK:
+                               if (iax2_ack_registry(&ies, &sin, fr.callno)) 
+@@ -7989,6 +7940,478 @@
+       return ast_pthread_create(&netthreadid, NULL, network_thread, NULL);
+ }
++struct iax_auth_frame *iax2_get_next_auth_frame(struct ast_iax2_auth_queue *authq) {
++      struct iax_auth_frame *frame = NULL;
++
++      /* sleep until the network_thread queues us a frame, then grab it and release the lock A.S.A.P. */
++      ast_mutex_lock(&authq->lock);
++      if (authq->count == 0) 
++              ast_cond_wait(&authq->cond, &authq->lock);
++      frame = authq->head;
++      if (frame) {
++          if (frame->next) {
++//            frame->next->prev = NULL;
++              authq->head = frame->next;
++          } else {
++              authq->head = NULL;
++              authq->tail = NULL;
++          }
++          authq->count--;
++      } else {
++          ast_log(LOG_ERROR, "I SHOULD NEVER HAPPEN! EXPECT SOME MAJOR KABOOM! DUCK AND COVER!\n");
++      }
++      ast_mutex_unlock(&authq->lock);
++      return frame;
++}
++
++
++void *auth_thread(void *data)
++{
++      /* 
++          The network_thread queues iax_frames into our queue and wakes us up.
++          We will authenticate IAX_COMMAND_NEWs and IAX_COMMAND_REGREQs.
++
++          We also have to process IAX_COMMAND_HANGUP when somebody hangs up a call
++          before it has been authorized!
++
++          If ever possible we shall not lock any iaxsl[...].
++      */
++      struct ast_iax2_auth_queue *authq = (struct ast_iax2_auth_queue *)data;
++      struct iax_frame *ifr;
++      struct iax_auth_frame *fr;
++      struct iax_ies *ies;
++      struct iax_ie_data ied0, ied1;
++      struct ast_channel *c;
++      char iabuf[INET_ADDRSTRLEN];
++      int exists;
++      int format;
++      int dequeued = 0;
++      char host_pref_buf[128];
++      char caller_pref_buf[128];
++      struct ast_codec_pref pref,rpref;
++      char *using_prefs = "mine";
++
++      if (!authq) {
++          ast_log(LOG_ERROR, "no queue!\n");
++          return NULL;
++      }
++
++      for(;;) {
++          fr = iax2_get_next_auth_frame(authq);
++          ifr = fr->frame;
++          ies = &fr->ies;
++              if (ifr) {
++                  if (ifr->callno > 0) {
++                      /* we will not lock iaxsl[ifr->callno], instead we will haveset a flag in iaxs_queued[ifr->callno]. 
++                         if this flag is set the socket_read thread may not touch iaxs[ifr->callno]. instead of
++                         processing the incoming packets there it has to queue them to us!
++                         This should only happen with IAX_COMMAND_HANGUP when hanging up a not-yet-established call.
++
++                         However we will try to deliver audio frames in socket_read. If we get audio data for call
++                         whos signalling frames have been queued we should be safe to just drop them.
++                         
++                         When we really want to destroy something we will aquire the lock first.
++                      */
++                      switch(fr->subclass) {
++                          case IAX_COMMAND_NEW:
++                              iax2_getpeername(fr->sin, iaxs[ifr->callno]->host, sizeof(iaxs[ifr->callno]->host), 1);
++                              if (check_access(ifr->callno, &fr->sin, ies)) {
++                                      /* They're not allowed on */
++                                      if (authdebug)
++                                              ast_log(LOG_NOTICE, "Rejected connect attempt from %s, who was trying to reach '%s@%s'\n", ast_inet_ntoa(iabuf, sizeof(iabuf), fr->sin.sin_addr), iaxs[ifr->callno]->exten, iaxs[ifr->callno]->context);
++                                      auth_fail(ifr->callno, IAX_COMMAND_REJECT);
++                                      break;
++                              }
++                              /* If we're in trunk mode, do it now, and update the trunk number in our frame before continuing */
++                              if (ast_test_flag(iaxs[ifr->callno], IAX_TRUNK)) {
++                                      ifr->callno = make_trunk(ifr->callno, 1);
++                              }
++                              /* This might re-enter the IAX code and need the lock */
++                              if (strcasecmp(iaxs[ifr->callno]->exten, "TBD")) {
++                              //      ast_mutex_unlock(&iaxsl[ifr->callno]);
++                                      exists = ast_exists_extension(NULL, iaxs[ifr->callno]->context, iaxs[ifr->callno]->exten, 1, iaxs[ifr->callno]->cid_num);
++                              //      ast_mutex_lock(&iaxsl[ifr->callno]);
++                              } else
++                                      exists = 0;
++                              if (ast_strlen_zero(iaxs[ifr->callno]->secret) && ast_strlen_zero(iaxs[ifr->callno]->inkeys)) {
++                                      if (strcmp(iaxs[ifr->callno]->exten, "TBD") && !exists) {
++                                              memset(&ied0, 0, sizeof(ied0));
++                                              iax_ie_append_str(&ied0, IAX_IE_CAUSE, "No such context/extension");
++                                              iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_NO_ROUTE_DESTINATION);
++                                              send_command_final(iaxs[ifr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1);
++                                              if (authdebug)
++                                                      ast_log(LOG_NOTICE, "Rejected connect attempt from %s, request '%s@%s' does not exist\n", ast_inet_ntoa(iabuf, sizeof(iabuf), fr->sin.sin_addr), iaxs[ifr->callno]->exten, iaxs[ifr->callno]->context);
++                                      } else {
++                                              /* Select an appropriate format */
++                                              if(ast_test_flag(iaxs[ifr->callno], IAX_CODEC_NOPREFS)) {
++                                                      if(ast_test_flag(iaxs[ifr->callno], IAX_CODEC_NOCAP)) {
++                                                              using_prefs = "reqonly";
++                                                      } else {
++                                                              using_prefs = "disabled";
++                                                      }
++                                                      format = iaxs[ifr->callno]->peerformat & iaxs[ifr->callno]->capability;
++                                                      memset(&pref, 0, sizeof(pref));
++                                                      strcpy(caller_pref_buf, "disabled");
++                                                      strcpy(host_pref_buf, "disabled");
++                                              } else {
++                                                      using_prefs = "mine";
++                                                      if(ies->codec_prefs) {
++                                                              ast_codec_pref_convert(&rpref, ies->codec_prefs, 32, 0);
++                                                              /* If we are codec_first_choice we let the caller have the 1st shot at picking the codec.*/
++                                                              if (ast_test_flag(iaxs[ifr->callno], IAX_CODEC_USER_FIRST)) {
++                                                                      pref = rpref;
++                                                                      using_prefs = "caller";
++                                                              } else {
++                                                                      pref = iaxs[ifr->callno]->prefs;
++                                                              }
++                                                      } else
++                                                              pref = iaxs[ifr->callno]->prefs;
++                                              
++                                                      format = ast_codec_choose(&pref, iaxs[ifr->callno]->capability & iaxs[ifr->callno]->peercapability, 0);
++                                                      ast_codec_pref_string(&rpref, caller_pref_buf, sizeof(caller_pref_buf) - 1);
++                                                      ast_codec_pref_string(&iaxs[ifr->callno]->prefs, host_pref_buf, sizeof(host_pref_buf) - 1);
++                                              }
++                                              if (!format) {
++                                                      if(!ast_test_flag(iaxs[ifr->callno], IAX_CODEC_NOCAP))
++                                                              format = iaxs[ifr->callno]->peercapability & iaxs[ifr->callno]->capability;
++                                                      if (!format) {
++                                                              memset(&ied0, 0, sizeof(ied0));
++                                                              iax_ie_append_str(&ied0, IAX_IE_CAUSE, "Unable to negotiate codec");
++                                                              iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL);
++                                                              send_command_final(iaxs[ifr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1);
++                                                              if (authdebug) {
++                                                                      if(ast_test_flag(iaxs[ifr->callno], IAX_CODEC_NOCAP))
++                                                                              ast_log(LOG_NOTICE, "Rejected connect attempt from %s, requested 0x%x incompatible with our capability 0x%x.\n", ast_inet_ntoa(iabuf, sizeof(iabuf), fr->sin.sin_addr), iaxs[ifr->callno]->peerformat, iaxs[ifr->callno]->capability);
++                                                                      else 
++                                                                              ast_log(LOG_NOTICE, "Rejected connect attempt from %s, requested/capability 0x%x/0x%x incompatible with our capability 0x%x.\n", ast_inet_ntoa(iabuf, sizeof(iabuf), fr->sin.sin_addr), iaxs[ifr->callno]->peerformat, iaxs[ifr->callno]->peercapability, iaxs[ifr->callno]->capability);
++                                                              }
++                                                      } else {
++                                                              /* Pick one... */
++                                                              if(ast_test_flag(iaxs[ifr->callno], IAX_CODEC_NOCAP)) {
++                                                                      if(!(iaxs[ifr->callno]->peerformat & iaxs[ifr->callno]->capability))
++                                                                              format = 0;
++                                                              } else {
++                                                                      if(ast_test_flag(iaxs[ifr->callno], IAX_CODEC_NOPREFS)) {
++                                                                              using_prefs = ast_test_flag(iaxs[ifr->callno], IAX_CODEC_NOCAP) ? "reqonly" : "disabled";
++                                                                              memset(&pref, 0, sizeof(pref));
++                                                                              format = ast_best_codec(iaxs[ifr->callno]->peercapability & iaxs[ifr->callno]->capability);
++                                                                              strcpy(caller_pref_buf,"disabled");
++                                                                              strcpy(host_pref_buf,"disabled");
++                                                                      } else {
++                                                                              using_prefs = "mine";
++                                                                              if(ies->codec_prefs) {
++                                                                                      /* Do the opposite of what we tried above. */
++                                                                                      if (ast_test_flag(iaxs[ifr->callno], IAX_CODEC_USER_FIRST)) {
++                                                                                              pref = iaxs[ifr->callno]->prefs;                                                                
++                                                                                      } else {
++                                                                                              pref = rpref;
++                                                                                              using_prefs = "caller";
++                                                                                      }
++                                                                                      format = ast_codec_choose(&pref, iaxs[ifr->callno]->peercapability & iaxs[ifr->callno]->capability, 1);
++                                                                      
++                                                                              } else /* if no codec_prefs IE do it the old way */
++                                                                                      format = ast_best_codec(iaxs[ifr->callno]->peercapability & iaxs[ifr->callno]->capability);     
++                                                                      }
++                                                              }
++
++                                                              if (!format) {
++                                                                      memset(&ied0, 0, sizeof(ied0));
++                                                                      iax_ie_append_str(&ied0, IAX_IE_CAUSE, "Unable to negotiate codec");
++                                                                      iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL);
++                                                                      ast_log(LOG_ERROR, "No best format in 0x%x???\n", iaxs[ifr->callno]->peercapability & iaxs[ifr->callno]->capability);
++                                                                      send_command_final(iaxs[ifr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1);
++                                                                      if (authdebug)
++                                                                              ast_log(LOG_NOTICE, "Rejected connect attempt from %s, requested/capability 0x%x/0x%x incompatible with our capability 0x%x.\n", ast_inet_ntoa(iabuf, sizeof(iabuf), fr->sin.sin_addr), iaxs[ifr->callno]->peerformat, iaxs[ifr->callno]->peercapability, iaxs[ifr->callno]->capability);
++                                                                      ast_set_flag(iaxs[ifr->callno], IAX_ALREADYGONE);       
++                                                                      break;
++                                                              }
++                                                      }
++                                              }
++                                              if (format) {
++                                                      /* No authentication required, let them in */
++                                                      memset(&ied1, 0, sizeof(ied1));
++                                                      iax_ie_append_int(&ied1, IAX_IE_FORMAT, format);
++                                                      send_command(iaxs[ifr->callno], AST_FRAME_IAX, IAX_COMMAND_ACCEPT, 0, ied1.buf, ied1.pos, -1);
++                                                      if (strcmp(iaxs[ifr->callno]->exten, "TBD")) {
++                                                              ast_set_flag(&iaxs[ifr->callno]->state, IAX_STATE_STARTED);
++                                                              if (option_verbose > 2) 
++                                                                      ast_verbose(VERBOSE_PREFIX_3 "Accepting UNAUTHENTICATED call from %s:\n"
++                                                                                              "%srequested format = %s,\n"
++                                                                                              "%srequested prefs = %s,\n"
++                                                                                              "%sactual format = %s,\n"
++                                                                                              "%shost prefs = %s,\n"
++                                                                                              "%spriority = %s\n",
++                                                                                              ast_inet_ntoa(iabuf, sizeof(iabuf), fr->sin.sin_addr), 
++                                                                                              VERBOSE_PREFIX_4,
++                                                                                              ast_getformatname(iaxs[ifr->callno]->peerformat), 
++                                                                                              VERBOSE_PREFIX_4,
++                                                                                              caller_pref_buf,
++                                                                                              VERBOSE_PREFIX_4,
++                                                                                              ast_getformatname(format), 
++                                                                                              VERBOSE_PREFIX_4,
++                                                                                              host_pref_buf, 
++                                                                                              VERBOSE_PREFIX_4,
++                                                                                              using_prefs);
++                                                              
++                                                              if(!(c = ast_iax2_new(ifr->callno, AST_STATE_RING, format))) {
++                                                                  ast_mutex_lock(&iaxsl[ifr->callno]);
++                                                                      iax2_destroy_nolock(ifr->callno);
++                                                                  ast_mutex_unlock(&iaxsl[ifr->callno]);
++                                                              }
++                                                      } else {
++                                                              ast_set_flag(&iaxs[ifr->callno]->state, IAX_STATE_TBD);
++                                                              /* If this is a TBD call, we're ready but now what...  */
++                                                              if (option_verbose > 2)
++                                                                      ast_verbose(VERBOSE_PREFIX_3 "Accepted unauthenticated TBD call from %s\n", ast_inet_ntoa(iabuf, sizeof(iabuf), fr->sin.sin_addr));
++                                                      }
++                                              }
++                                      }
++                                      break;
++                              }
++                              if (iaxs[ifr->callno]->authmethods & IAX_AUTH_MD5)
++                                      merge_encryption(iaxs[ifr->callno],ies->encmethods);
++                              else
++                                      iaxs[ifr->callno]->encmethods = 0;
++                              authenticate_request(iaxs[ifr->callno]);
++                              ast_set_flag(&iaxs[ifr->callno]->state, IAX_STATE_AUTHENTICATED);
++                              break;
++                          case IAX_COMMAND_REGREQ:
++                          case IAX_COMMAND_REGREL:
++              //                  usleep(1000000);
++                              if (register_verify(ifr->callno, &fr->sin, ies)) {
++                                      /* Send delayed failure */
++                                      auth_fail(ifr->callno, IAX_COMMAND_REGREJ);
++                                  break;
++                              }
++                              if ((ast_strlen_zero(iaxs[ifr->callno]->secret) && ast_strlen_zero(iaxs[ifr->callno]->inkeys)) || ast_test_flag(&iaxs[ifr->callno]->state, IAX_STATE_AUTHENTICATED)) {
++                                  if (fr->subclass == IAX_COMMAND_REGREL)
++                                      memset(&fr->sin, 0, sizeof(struct sockaddr_in));
++                                  if (update_registry(iaxs[ifr->callno]->peer, &fr->sin, ifr->callno, ies->devicetype, fr->fd, ies->refresh))
++                                      ast_log(LOG_WARNING, "Registry error\n"); 
++                                  if (ies->provverpres && ies->serviceident && fr->sin.sin_addr.s_addr)
++                                      check_provisioning(&fr->sin, fr->fd, ies->serviceident, ies->provver);
++                                  /* update registry leaves us locked, so we have to unlock to not deadlock */
++                                  iaxs_queued[ifr->callno]--;
++                                  if (iaxs_queued[ifr->callno] < 0) iaxs_queued[ifr->callno] = 0;
++                                  ast_mutex_unlock(&iaxsl[ifr->callno]);
++                                  break;
++                              }
++                              registry_authrequest(iaxs[ifr->callno]->peer, ifr->callno);
++                              break;
++                          case IAX_COMMAND_HANGUP:
++                              /* Here we really have to lock */
++                              ast_mutex_lock(&iaxsl[ifr->callno]);
++                              if (iaxs[ifr->callno]) {
++                                  ast_set_flag(iaxs[ifr->callno], IAX_ALREADYGONE);
++                                  ast_log(LOG_DEBUG, "Asynchronously destroying %d, having received hangup\n", ifr->callno);
++                                  /* Set hangup cause according to remote */
++                                  if (ies->causecode && iaxs[ifr->callno]->owner)
++                                      iaxs[ifr->callno]->owner->hangupcause = ies->causecode;
++                                  iax2_destroy_nolock(ifr->callno);
++                              }
++                              iaxs_queued[ifr->callno]--;
++                              if (iaxs_queued[ifr->callno] < 0) iaxs_queued[ifr->callno] = 0;
++                              dequeued = 1;
++                              ast_mutex_unlock(&iaxsl[ifr->callno]);
++                              break;
++                      case IAX_COMMAND_INVAL:
++                              /* Here we really have to lock */
++                              ast_mutex_lock(&iaxsl[ifr->callno]);
++                              if (iaxs[ifr->callno]) {
++                                  iaxs[ifr->callno]->error = ENOTCONN;
++                                  ast_log(LOG_DEBUG, "Asynchronously destroying %d, having received INVAL\n", ifr->callno);
++                                  iax2_destroy_nolock(ifr->callno);
++                                  if (option_debug)
++                                      ast_log(LOG_DEBUG, "Destroying call %d\n", ifr->callno);
++                              }
++                              iaxs_queued[ifr->callno]--;
++                              if (iaxs_queued[ifr->callno] < 0) iaxs_queued[ifr->callno] = 0;
++                              dequeued = 1;
++                              ast_mutex_unlock(&iaxsl[ifr->callno]);
++                              break;
++                      case IAX_COMMAND_AUTHREP:
++                              /* Ignore once we've started */
++                              if (ast_test_flag(&iaxs[ifr->callno]->state, IAX_STATE_STARTED | IAX_STATE_TBD)) {
++                                  ast_log(LOG_WARNING, "Call on %s is already up, can't start on it\n", iaxs[ifr->callno]->owner ? iaxs[ifr->callno]->owner->name : "<Unknown>");
++                                  break;
++                              }
++                              if (authenticate_verify(iaxs[ifr->callno], ies)) {
++                                      if (authdebug)
++                                              ast_log(LOG_NOTICE, "Host %s failed to authenticate as %s\n", ast_inet_ntoa(iabuf, sizeof(iabuf), iaxs[ifr->callno]->addr.sin_addr), iaxs[ifr->callno]->username);
++                                      memset(&ied0, 0, sizeof(ied0));
++                                      auth_fail(ifr->callno, IAX_COMMAND_REJECT);
++                                      break;
++                              }
++                              ast_mutex_lock(&iaxsl[ifr->callno]);
++                              if (strcasecmp(iaxs[ifr->callno]->exten, "TBD")) {
++                                      /* This might re-enter the IAX code and need the lock */
++                                      exists = ast_exists_extension(NULL, iaxs[ifr->callno]->context, iaxs[ifr->callno]->exten, 1, iaxs[ifr->callno]->cid_num);
++                              } else
++                                      exists = 0;
++                                  if (strcmp(iaxs[ifr->callno]->exten, "TBD") && !exists) {
++                                      if (authdebug)
++                                              ast_log(LOG_NOTICE, "Rejected connect attempt from %s, request '%s@%s' does not exist\n", ast_inet_ntoa(iabuf, sizeof(iabuf), fr->sin.sin_addr), iaxs[ifr->callno]->exten, iaxs[ifr->callno]->context);
++                                      memset(&ied0, 0, sizeof(ied0));
++                                      iax_ie_append_str(&ied0, IAX_IE_CAUSE, "No such context/extension");
++                                      iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_NO_ROUTE_DESTINATION);
++                                      send_command_final(iaxs[ifr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1);
++                              } else {
++                                      /* Select an appropriate format */
++                                      if(ast_test_flag(iaxs[ifr->callno], IAX_CODEC_NOPREFS)) {
++                                              if(ast_test_flag(iaxs[ifr->callno], IAX_CODEC_NOCAP)) {
++                                                      using_prefs = "reqonly";
++                                              } else {
++                                                      using_prefs = "disabled";
++                                              }
++                                              format = iaxs[ifr->callno]->peerformat & iaxs[ifr->callno]->capability;
++                                              memset(&pref, 0, sizeof(pref));
++                                              strcpy(caller_pref_buf, "disabled");
++                                              strcpy(host_pref_buf, "disabled");
++                                      } else {
++                                              using_prefs = "mine";
++                                              if(ies->codec_prefs) {
++                                                      /* If we are codec_first_choice we let the caller have the 1st shot at picking the codec.*/
++                                                      ast_codec_pref_convert(&rpref, ies->codec_prefs, 32, 0);
++                                                      if (ast_test_flag(iaxs[ifr->callno], IAX_CODEC_USER_FIRST)) {
++                                                              ast_codec_pref_convert(&pref, ies->codec_prefs, 32, 0);
++                                                              using_prefs = "caller";
++                                                      } else {
++                                                              pref = iaxs[ifr->callno]->prefs;
++                                                      }
++                                              } else /* if no codec_prefs IE do it the old way */
++                                                      pref = iaxs[ifr->callno]->prefs;
++                                      
++                                              format = ast_codec_choose(&pref, iaxs[ifr->callno]->capability & iaxs[ifr->callno]->peercapability, 0);
++                                              ast_codec_pref_string(&rpref, caller_pref_buf, sizeof(caller_pref_buf) - 1);
++                                              ast_codec_pref_string(&iaxs[ifr->callno]->prefs, host_pref_buf, sizeof(host_pref_buf) - 1);
++                                      }
++                                      if (!format) {
++                                              if(!ast_test_flag(iaxs[ifr->callno], IAX_CODEC_NOCAP)) {
++                                                      ast_log(LOG_DEBUG, "We don't do requested format %s, falling back to peer capability %d\n", ast_getformatname(iaxs[ifr->callno]->peerformat), iaxs[ifr->callno]->peercapability);
++                                                      format = iaxs[ifr->callno]->peercapability & iaxs[ifr->callno]->capability;
++                                              }
++                                              if (!format) {
++                                                      if (authdebug) {
++                                                              if(ast_test_flag(iaxs[ifr->callno], IAX_CODEC_NOCAP)) 
++                                                                      ast_log(LOG_NOTICE, "Rejected connect attempt from %s, requested 0x%x incompatible with our capability 0x%x.\n", ast_inet_ntoa(iabuf, sizeof(iabuf), fr->sin.sin_addr), iaxs[ifr->callno]->peerformat, iaxs[ifr->callno]->capability);
++                                                              else
++                                                                      ast_log(LOG_NOTICE, "Rejected connect attempt from %s, requested/capability 0x%x/0x%x incompatible with our capability 0x%x.\n", ast_inet_ntoa(iabuf, sizeof(iabuf), fr->sin.sin_addr), iaxs[ifr->callno]->peerformat, iaxs[ifr->callno]->peercapability, iaxs[ifr->callno]->capability);
++                                                      }
++                                                      memset(&ied0, 0, sizeof(ied0));
++                                                      iax_ie_append_str(&ied0, IAX_IE_CAUSE, "Unable to negotiate codec");
++                                                      iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL);
++                                                      send_command_final(iaxs[ifr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1);
++                                              } else {
++                                                      /* Pick one... */
++                                                      if(ast_test_flag(iaxs[ifr->callno], IAX_CODEC_NOCAP)) {
++                                                              if(!(iaxs[ifr->callno]->peerformat & iaxs[ifr->callno]->capability))
++                                                                      format = 0;
++                                                      } else {
++                                                              if(ast_test_flag(iaxs[ifr->callno], IAX_CODEC_NOPREFS)) {
++                                                                      using_prefs = ast_test_flag(iaxs[ifr->callno], IAX_CODEC_NOCAP) ? "reqonly" : "disabled";
++                                                                      memset(&pref, 0, sizeof(pref));
++                                                                      format = ast_test_flag(iaxs[ifr->callno], IAX_CODEC_NOCAP) ?
++                                                                              iaxs[ifr->callno]->peerformat : ast_best_codec(iaxs[ifr->callno]->peercapability & iaxs[ifr->callno]->capability);
++                                                                      strcpy(caller_pref_buf,"disabled");
++                                                                      strcpy(host_pref_buf,"disabled");
++                                                              } else {
++                                                                      using_prefs = "mine";
++                                                                      if(ies->codec_prefs) {
++                                                                              /* Do the opposite of what we tried above. */
++                                                                              if (ast_test_flag(iaxs[ifr->callno], IAX_CODEC_USER_FIRST)) {
++                                                                                      pref = iaxs[ifr->callno]->prefs;                                                
++                                                                              } else {
++                                                                                      pref = rpref;
++                                                                                      using_prefs = "caller";
++                                                                              }
++                                                                              format = ast_codec_choose(&pref, iaxs[ifr->callno]->peercapability & iaxs[ifr->callno]->capability, 1);
++                                                                      } else /* if no codec_prefs IE do it the old way */
++                                                                              format = ast_best_codec(iaxs[ifr->callno]->peercapability & iaxs[ifr->callno]->capability);     
++                                                              }
++                                                      }
++                                                      if (!format) {
++                                                              ast_log(LOG_ERROR, "No best format in 0x%x???\n", iaxs[ifr->callno]->peercapability & iaxs[ifr->callno]->capability);
++                                                              if (authdebug) {
++                                                                      if(ast_test_flag(iaxs[ifr->callno], IAX_CODEC_NOCAP))
++                                                                              ast_log(LOG_NOTICE, "Rejected connect attempt from %s, requested 0x%x incompatible with our capability 0x%x.\n", ast_inet_ntoa(iabuf, sizeof(iabuf), fr->sin.sin_addr), iaxs[ifr->callno]->peerformat, iaxs[ifr->callno]->capability);
++                                                                      else
++                                                                              ast_log(LOG_NOTICE, "Rejected connect attempt from %s, requested/capability 0x%x/0x%x incompatible with our capability 0x%x.\n", ast_inet_ntoa(iabuf, sizeof(iabuf), fr->sin.sin_addr), iaxs[ifr->callno]->peerformat, iaxs[ifr->callno]->peercapability, iaxs[ifr->callno]->capability);
++                                                              }
++                                                              memset(&ied0, 0, sizeof(ied0));
++                                                              iax_ie_append_str(&ied0, IAX_IE_CAUSE, "Unable to negotiate codec");
++                                                              iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL);
++                                                              send_command_final(iaxs[ifr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1);
++                                                      }
++                                              }
++                                      }
++                                      if (format) {
++                                              /* Authentication received */
++                                              memset(&ied1, 0, sizeof(ied1));
++                                              iax_ie_append_int(&ied1, IAX_IE_FORMAT, format);
++                                              send_command(iaxs[ifr->callno], AST_FRAME_IAX, IAX_COMMAND_ACCEPT, 0, ied1.buf, ied1.pos, -1);
++                                              if (strcmp(iaxs[ifr->callno]->exten, "TBD")) {
++                                                      ast_set_flag(&iaxs[ifr->callno]->state, IAX_STATE_STARTED);
++                                                      if (option_verbose > 2) 
++                                                              ast_verbose(VERBOSE_PREFIX_3 "Accepting AUTHENTICATED call from %s:\n"
++                                                                                      "%srequested format = %s,\n"
++                                                                                      "%srequested prefs = %s,\n"
++                                                                                      "%sactual format = %s,\n"
++                                                                                      "%shost prefs = %s,\n"
++                                                                                      "%spriority = %s\n", 
++                                                                                      ast_inet_ntoa(iabuf, sizeof(iabuf), fr->sin.sin_addr), 
++                                                                                      VERBOSE_PREFIX_4,
++                                                                                      ast_getformatname(iaxs[ifr->callno]->peerformat),
++                                                                                      VERBOSE_PREFIX_4,
++                                                                                      caller_pref_buf,
++                                                                                      VERBOSE_PREFIX_4,
++                                                                                      ast_getformatname(format),
++                                                                                      VERBOSE_PREFIX_4,
++                                                                                      host_pref_buf,
++                                                                                      VERBOSE_PREFIX_4,
++                                                                                      using_prefs);
++
++                                                      ast_set_flag(&iaxs[ifr->callno]->state, IAX_STATE_STARTED);
++                                                      if(!(c = ast_iax2_new(ifr->callno, AST_STATE_RING, format)))
++                                                              iax2_destroy_nolock(ifr->callno);
++                                              } else {
++                                                      ast_set_flag(&iaxs[ifr->callno]->state, IAX_STATE_TBD);
++                                                      /* If this is a TBD call, we're ready but now what...  */
++                                                      if (option_verbose > 2)
++                                                              ast_verbose(VERBOSE_PREFIX_3 "Accepted AUTHENTICATED TBD call from %s\n", ast_inet_ntoa(iabuf, sizeof(iabuf), fr->sin.sin_addr));
++                                              }
++                                      }
++                              }
++                              iaxs_queued[ifr->callno]--;
++                              if (iaxs_queued[ifr->callno] < 0) iaxs_queued[ifr->callno] = 0;
++                              ast_mutex_unlock(&iaxsl[ifr->callno]);
++                      }
++                      if (!dequeued) {
++                          ast_mutex_lock(&iaxsl[ifr->callno]);
++                              iaxs_queued[ifr->callno]--;
++                              if (iaxs_queued[ifr->callno] < 0) iaxs_queued[ifr->callno] = 0;
++                          ast_mutex_unlock(&iaxsl[ifr->callno]);
++                      }
++                  }
++              iax_frame_free(ifr);
++              free(fr);
++              fr = NULL;
++              }
++      
++      }
++      return NULL;
++}
++
++
++static int start_auth_thread(void)
++{
++      return ast_pthread_create(&auththreadid, NULL, auth_thread, &callq);
++}
++
++static int start_reg_thread(void)
++{
++      return ast_pthread_create(&regthreadid, NULL, auth_thread, &regq);
++}
++
+ static struct iax2_context *build_context(char *context)
+ {
+       struct iax2_context *con = malloc(sizeof(struct iax2_context));
+@@ -8882,6 +9305,7 @@
+       tmpstr = ast_strdupa(data);
+       parse_dial_string(tmpstr, &pds);
++ast_log(LOG_NOTICE, "calling create_addr here\n");
+       /* Populate our address from the given */
+       if (create_addr(pds.peer, &sin, &cai))
+               return -1;
+@@ -9492,6 +9916,11 @@
+ static int __unload_module(void)
+ {
+       int x;
++      /* Cancel the authentication thread */
++      if (auththreadid != AST_PTHREADT_NULL) {
++              pthread_cancel(auththreadid);
++              pthread_join(auththreadid, NULL);
++      }
+       /* Cancel the network thread, close the net socket */
+       if (netthreadid != AST_PTHREADT_NULL) {
+               pthread_cancel(netthreadid);
+@@ -9514,6 +9943,8 @@
+ int unload_module()
+ {
++      ast_mutex_destroy(&regq.lock);
++      ast_mutex_destroy(&callq.lock);
+       ast_mutex_destroy(&iaxq.lock);
+       ast_mutex_destroy(&userl.lock);
+       ast_mutex_destroy(&peerl.lock);
+@@ -9535,6 +9966,9 @@
+       struct ast_netsock *ns;
+       struct sockaddr_in sin;
+       
++      /* you never can tell */
++      memset(iaxs_queued, 0, sizeof(iaxs_queued));
++      
+       ast_custom_function_register(&iaxpeer_function);
+       iax_set_output(iax_debug_output);
+@@ -9577,7 +10011,14 @@
+       }
+       ast_netsock_init(netsock);
++      gethostname(servername, sizeof(servername) - 1);
++      ast_log(LOG_NOTICE, "servername = %s\n", servername);
++
+       ast_mutex_init(&iaxq.lock);
++      ast_mutex_init(&regq.lock);
++      ast_cond_init(&regq.cond, NULL);
++      ast_mutex_init(&callq.lock);
++      ast_cond_init(&callq.cond, NULL);
+       ast_mutex_init(&userl.lock);
+       ast_mutex_init(&peerl.lock);
+       ast_mutex_init(&waresl.lock);
+@@ -9621,6 +10062,16 @@
+               ast_netsock_release(netsock);
+       }
++      res = start_reg_thread();
++      if (res) {
++              ast_log(LOG_ERROR, "Unable to start registration thread\n");
++      }
++
++      res = start_auth_thread();
++      if (res) {
++              ast_log(LOG_ERROR, "Unable to start authentication thread\n");
++      }
++
+       for (reg = registrations; reg; reg = reg->next)
+               iax2_do_register(reg);
+       ast_mutex_lock(&peerl.lock);
+diff -urN asterisk-1.2.4/res/Makefile asterisk-1.2.4.carrier/res/Makefile
+--- asterisk-1.2.4/res/Makefile        2006-01-31 09:41:43.000000000 +0100
++++ asterisk-1.2.4.carrier/res/Makefile        2006-01-31 15:04:30.000000000 +0100
+@@ -13,6 +13,21 @@
+ MODS=res_indications.so res_monitor.so res_adsi.so res_agi.so res_features.so res_watchdog.so
++#
++# MySQL stuff...  Autoconf anyone??
++#
++MODS+=$(shell if [ -d /usr/local/mysql/include ] || [ -d /usr/include/mysql ] || [ -d /usr/local/include/mysql ] || [ -d /opt/mysql/include ]; then echo "res_config_mysql.so"; fi)
++CFLAGS+=$(shell if [ -d /usr/local/mysql/include ]; then echo "-I/usr/local/mysql/include"; fi)
++CFLAGS+=$(shell if [ -d /usr/include/mysql ]; then echo "-I/usr/include/mysql"; fi)
++CFLAGS+=$(shell if [ -d /usr/local/include/mysql ]; then echo "-I/usr/local/include/mysql"; fi)
++CFLAGS+=$(shell if [ -d /opt/mysql/include/mysql ]; then echo "-I/opt/mysql/include/mysql"; fi)
++MLFLAGS=
++MLFLAGS+=$(shell if [ -d /usr/lib/mysql ]; then echo "-L/usr/lib/mysql"; fi)
++MLFLAGS+=$(shell if [ -d /usr/lib64/mysql ]; then echo "-L/usr/lib64/mysql"; fi)
++MLFLAGS+=$(shell if [ -d /usr/local/mysql/lib ]; then echo "-L/usr/local/mysql/lib"; fi)
++MLFLAGS+=$(shell if [ -d /usr/local/lib/mysql ]; then echo "-L/usr/local/lib/mysql"; fi)
++MLFLAGS+=$(shell if [ -d /opt/mysql/lib/mysql ]; then echo "-L/opt/mysql/lib/mysql"; fi)
++
+ ifneq ($(wildcard $(CROSS_COMPILE_TARGET)/usr/include/odbcinst.h)$(wildcard $(CROSS_COMPILE_TARGET)/usr/local/include/odbcinst.h),)
+   ifneq (${OSARCH},FreeBSD)
+     MODS+=res_config_odbc.so
+@@ -109,6 +124,9 @@
+ res_config_odbc.so: res_config_odbc.o
+       $(CC) $(SOLINK) -o $@ ${CYGSOLINK} $< ${CYGSOLIB} ${CYG_RES_CONFIG_ODBC_LIB}
++res_config_mysql.so: res_config_mysql.o
++      $(CC) $(SOLINK) -o $@ $< -lmysqlclient -lz $(MLFLAGS)
++
+ ifneq ($(wildcard .depend),)
+   include .depend
+ endif
+diff -urN asterisk-1.2.4/res/res_config_mysql.c asterisk-1.2.4.carrier/res/res_config_mysql.c
+--- asterisk-1.2.4/res/res_config_mysql.c      1970-01-01 01:00:00.000000000 +0100
++++ asterisk-1.2.4.carrier/res/res_config_mysql.c      2006-01-31 14:54:49.000000000 +0100
+@@ -0,0 +1,680 @@
++/*
++ * Asterisk -- A telephony toolkit for Linux.
++ *
++ * Copyright (C) 1999-2005, Digium, Inc.
++ *
++ * Mark Spencer <markster@digium.com>  - Asterisk Author
++ * Matthew Boehm <mboehm@cytelcom.com> - MySQL RealTime Driver Author
++ *
++ * res_config_mysql.c <mysql plugin for RealTime configuration engine>
++ *
++ * v2.0   - (10-07-05) - mutex_lock fixes (bug #4973, comment #0034602)
++ *
++ * v1.9   - (08-19-05) - Added support to correctly honor the family database specified
++ *                       in extconfig.conf (bug #4973)
++ *
++ * v1.8   - (04-21-05) - Modified return values of update_mysql to better indicate
++ *                       what really happened.
++ *
++ * v1.7   - (01-28-05) - Fixed non-initialization of ast_category struct
++ *                       in realtime_multi_mysql function which caused segfault. 
++ *
++ * v1.6   - (00-00-00) - Skipped to bring comments into sync with version number in CVS.
++ *
++ * v1.5.1 - (01-26-05) - Added better(?) locking stuff
++ *
++ * v1.5   - (01-26-05) - Brought up to date with new config.h changes (bug #3406)
++ *                     - Added in extra locking provided by georg (bug #3248)
++ *
++ * v1.4   - (12-02-04) - Added realtime_multi_mysql function
++ *                        This function will return an ast_config with categories,
++ *                        unlike standard realtime_mysql which only returns
++ *                        a linked list of ast_variables
++ *
++ * v1.3   - (12-01-04) - Added support other operators
++ *                       Ex: =, !=, LIKE, NOT LIKE, RLIKE, etc...
++ *
++ * v1.2   - (11-DD-04) - Added reload. Updated load and unload.
++ *                       Code beautification (doc/CODING-GUIDELINES)
++ */
++
++#include <asterisk/channel.h>
++#include <asterisk/logger.h>
++#include <asterisk/config.h>
++#include <asterisk/module.h>
++#include <asterisk/lock.h>
++#include <asterisk/options.h>
++#include <asterisk/cli.h>
++#include <asterisk/utils.h>
++#include <stdlib.h>
++#include <string.h>
++#include <mysql.h>
++#include <mysql_version.h>
++#include <errmsg.h>
++
++static char *res_config_mysql_desc = "MySQL RealTime Configuration Driver";
++
++AST_MUTEX_DEFINE_STATIC(mysql_lock);
++#define RES_CONFIG_MYSQL_CONF "res_mysql.conf"
++MYSQL         mysql;
++static char   dbhost[50];
++static char   dbuser[50];
++static char   dbpass[50];
++static char   dbname[50];
++static char   dbsock[50];
++static int    dbport;
++static int    connected;
++static time_t connect_time;
++
++static int parse_config(void);
++static int mysql_reconnect(const char *database);
++static int realtime_mysql_status(int fd, int argc, char **argv);
++
++STANDARD_LOCAL_USER;
++
++LOCAL_USER_DECL;
++
++static char cli_realtime_mysql_status_usage[] =
++"Usage: realtime mysql status\n"
++"       Shows connection information for the MySQL RealTime driver\n";
++
++static struct ast_cli_entry cli_realtime_mysql_status = {
++        { "realtime", "mysql", "status", NULL }, realtime_mysql_status,
++        "Shows connection information for the MySQL RealTime driver", cli_realtime_mysql_status_usage, NULL };
++
++static struct ast_variable *realtime_mysql(const char *database, const char *table, va_list ap)
++{
++      MYSQL_RES *result;
++      MYSQL_ROW row;
++      MYSQL_FIELD *fields;
++      int numFields, i;
++      char sql[256];
++      char *stringp;
++      char *chunk;
++      char *op;
++      const char *newparam, *newval;
++      struct ast_variable *var=NULL, *prev=NULL;
++
++      if(!table) {
++              ast_log(LOG_WARNING, "MySQL RealTime: No table specified.\n");
++              return NULL;
++      }
++
++      /* Get the first parameter and first value in our list of passed paramater/value pairs */
++      newparam = va_arg(ap, const char *);
++      newval = va_arg(ap, const char *);
++      if(!newparam || !newval)  {
++              ast_log(LOG_WARNING, "MySQL RealTime: Realtime retrieval requires at least 1 parameter and 1 value to search on.\n");
++              mysql_close(&mysql);
++              return NULL;
++      }
++
++      /* Create the first part of the query using the first parameter/value pairs we just extracted
++         If there is only 1 set, then we have our query. Otherwise, loop thru the list and concat */
++
++      if(!strchr(newparam, ' ')) op = " ="; else op = "";
++
++      snprintf(sql, sizeof(sql), "SELECT * FROM %s WHERE %s%s '%s'", table, newparam, op, newval);
++      while((newparam = va_arg(ap, const char *))) {
++              newval = va_arg(ap, const char *);
++              if(!strchr(newparam, ' ')) op = " ="; else op = "";
++              snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " AND %s%s '%s'", newparam, op, newval);
++      }
++      va_end(ap);
++
++      ast_log(LOG_DEBUG, "MySQL RealTime: Retrieve SQL: %s\n", sql);
++
++      /* We now have our complete statement; Lets connect to the server and execute it. */
++      ast_mutex_lock(&mysql_lock);
++      if(!mysql_reconnect(database)) {
++              ast_mutex_unlock(&mysql_lock);
++              return NULL;
++      }
++      
++//    ast_log(LOG_NOTICE, "SQL: %s\m", sql);
++
++      if(mysql_real_query(&mysql, sql, strlen(sql))) {
++              ast_log(LOG_WARNING, "MySQL RealTime: Failed to query database. Check debug for more info.\n");
++              ast_log(LOG_DEBUG, "MySQL RealTime: Query: %s\n", sql);
++              ast_log(LOG_DEBUG, "MySQL RealTime: Query Failed because: %s\n", mysql_error(&mysql));
++              ast_mutex_unlock(&mysql_lock);
++              return NULL;
++      }
++
++      if((result = mysql_store_result(&mysql))) {
++              numFields = mysql_num_fields(result);
++              fields = mysql_fetch_fields(result);
++
++              while((row = mysql_fetch_row(result))) {
++                      for(i = 0; i < numFields; i++) {
++                              stringp = row[i];
++                              while(stringp) {
++                                      chunk = strsep(&stringp, ";");
++                                      if(chunk && !ast_strlen_zero(ast_strip(chunk))) {
++                                              if(prev) {
++                                                      prev->next = ast_variable_new(fields[i].name, chunk);
++                                                      if (prev->next) {
++                                                              prev = prev->next;
++                                                      }
++                                              } else {
++                                                      prev = var = ast_variable_new(fields[i].name, chunk);
++                                              }
++                                      }
++                              }
++                      }
++              }
++      } else {                                
++              ast_log(LOG_WARNING, "MySQL RealTime: Could not find any rows in table %s.\n", table);
++      }
++
++      mysql_free_result(result);
++      ast_mutex_unlock(&mysql_lock);
++
++      return var;
++}
++
++static struct ast_config *realtime_multi_mysql(const char *database, const char *table, va_list ap)
++{
++      MYSQL_RES *result;
++      MYSQL_ROW row;
++      MYSQL_FIELD *fields;
++      int numFields, i;
++      char sql[256];
++      const char *initfield = NULL;
++      char *stringp;
++      char *chunk;
++      char *op;
++      const char *newparam, *newval;
++      struct ast_realloca ra;
++      struct ast_variable *var=NULL;
++      struct ast_config *cfg = NULL;
++      struct ast_category *cat = NULL;
++
++      if(!table) {
++              ast_log(LOG_WARNING, "MySQL RealTime: No table specified.\n");
++              return NULL;
++      }
++      
++      memset(&ra, 0, sizeof(ra));
++
++      cfg = ast_config_new();
++      if (!cfg) {
++              /* If I can't alloc memory at this point, why bother doing anything else? */
++              ast_log(LOG_WARNING, "Out of memory!\n");
++              return NULL;
++      }
++
++      /* Get the first parameter and first value in our list of passed paramater/value pairs */
++      newparam = va_arg(ap, const char *);
++      newval = va_arg(ap, const char *);
++      if(!newparam || !newval)  {
++              ast_log(LOG_WARNING, "MySQL RealTime: Realtime retrieval requires at least 1 parameter and 1 value to search on.\n");
++              mysql_close(&mysql);
++              return NULL;
++      }
++
++      initfield = ast_strdupa(newparam);
++      if(initfield && (op = strchr(initfield, ' '))) {
++              *op = '\0';
++      }
++
++      /* Create the first part of the query using the first parameter/value pairs we just extracted
++         If there is only 1 set, then we have our query. Otherwise, loop thru the list and concat */
++
++      if(!strchr(newparam, ' ')) op = " ="; else op = "";
++
++      snprintf(sql, sizeof(sql), "SELECT * FROM %s WHERE %s%s '%s'", table, newparam, op, newval);
++      while((newparam = va_arg(ap, const char *))) {
++              newval = va_arg(ap, const char *);
++              if(!strchr(newparam, ' ')) op = " ="; else op = "";
++              snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " AND %s%s '%s'", newparam, op, newval);
++      }
++
++      if(initfield) {
++              snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " ORDER BY %s", initfield);
++      }
++
++      va_end(ap);
++
++      ast_log(LOG_DEBUG, "MySQL RealTime: Retrieve SQL: %s\n", sql);
++
++      /* We now have our complete statement; Lets connect to the server and execute it. */
++      ast_mutex_lock(&mysql_lock);
++      if(!mysql_reconnect(database)) {
++              ast_mutex_unlock(&mysql_lock);
++              return NULL;
++      }
++
++      if(mysql_real_query(&mysql, sql, strlen(sql))) {
++              ast_log(LOG_WARNING, "MySQL RealTime: Failed to query database. Check debug for more info.\n");
++              ast_log(LOG_DEBUG, "MySQL RealTime: Query: %s\n", sql);
++              ast_log(LOG_DEBUG, "MySQL RealTime: Query Failed because: %s\n", mysql_error(&mysql));
++              ast_mutex_unlock(&mysql_lock);
++              return NULL;
++      }
++
++      if((result = mysql_store_result(&mysql))) {
++              numFields = mysql_num_fields(result);
++              fields = mysql_fetch_fields(result);
++
++              while((row = mysql_fetch_row(result))) {
++                      var = NULL;
++                      cat = ast_category_new("");
++                      if(!cat) {
++                              ast_log(LOG_WARNING, "Out of memory!\n");
++                              continue;
++                      }
++                      for(i = 0; i < numFields; i++) {
++                              stringp = row[i];
++                              while(stringp) {
++                                      chunk = strsep(&stringp, ";");
++                                      if(chunk && !ast_strlen_zero(ast_strip(chunk))) {
++                                              if(initfield && !strcmp(initfield, fields[i].name)) {
++                                                      ast_category_rename(cat, chunk);
++                                              }
++                                              var = ast_variable_new(fields[i].name, chunk);
++                                              ast_variable_append(cat, var);
++                                      }
++                              }
++                      }
++                      ast_category_append(cfg, cat);
++              }
++      } else {
++              ast_log(LOG_WARNING, "MySQL RealTime: Could not find any rows in table %s.\n", table);
++      }
++
++      mysql_free_result(result);
++      ast_mutex_unlock(&mysql_lock);
++
++      return cfg;
++}
++
++static int update_mysql(const char *database, const char *table, const char *keyfield, const char *lookup, va_list ap)
++{
++      my_ulonglong numrows;
++      char sql[256];
++      const char *newparam, *newval;
++
++      if(!table) {
++              ast_log(LOG_WARNING, "MySQL RealTime: No table specified.\n");
++               return -1;
++      }
++
++      /* Get the first parameter and first value in our list of passed paramater/value pairs */
++      newparam = va_arg(ap, const char *);
++      newval = va_arg(ap, const char *);
++      if(!newparam || !newval)  {
++              ast_log(LOG_WARNING, "MySQL RealTime: Realtime retrieval requires at least 1 parameter and 1 value to search on.\n");
++              mysql_close(&mysql);
++               return -1;
++      }
++
++      /* Create the first part of the query using the first parameter/value pairs we just extracted
++         If there is only 1 set, then we have our query. Otherwise, loop thru the list and concat */
++
++      snprintf(sql, sizeof(sql), "UPDATE %s SET %s = '%s'", table, newparam, newval);
++      while((newparam = va_arg(ap, const char *))) {
++              newval = va_arg(ap, const char *);
++              snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), ", %s = '%s'", newparam, newval);
++      }
++      va_end(ap);
++      snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " WHERE %s = '%s'", keyfield, lookup);
++
++      ast_log(LOG_DEBUG,"MySQL RealTime: Update SQL: %s\n", sql);
++
++      /* We now have our complete statement; Lets connect to the server and execute it. */
++      ast_mutex_lock(&mysql_lock);
++      if(!mysql_reconnect(database)) {
++              ast_mutex_unlock(&mysql_lock);
++              return -1;
++      }
++
++      if(mysql_real_query(&mysql, sql, strlen(sql))) {
++              ast_log(LOG_WARNING, "MySQL RealTime: Failed to query database. Check debug for more info.\n");
++              ast_log(LOG_DEBUG, "MySQL RealTime: Query: %s\n", sql);
++              ast_log(LOG_DEBUG, "MySQL RealTime: Query Failed because: %s\n", mysql_error(&mysql));
++              ast_mutex_unlock(&mysql_lock);
++              return -1;
++      }
++
++      numrows = mysql_affected_rows(&mysql);
++      ast_mutex_unlock(&mysql_lock);
++
++      ast_log(LOG_DEBUG,"MySQL RealTime: Updated %llu rows on table: %s\n", numrows, table);
++
++      /* From http://dev.mysql.com/doc/mysql/en/mysql-affected-rows.html
++       * An integer greater than zero indicates the number of rows affected
++       * Zero indicates that no records were updated
++       * -1 indicates that the query returned an error (although, if the query failed, it should have been caught above.)
++      */
++
++      if(numrows >= 0)
++              return (int)numrows;
++
++      return -1;
++}
++
++static struct ast_config *config_mysql(const char *database, const char *table, const char *file, struct ast_config *cfg)
++{
++      MYSQL_RES *result;
++      MYSQL_ROW row;
++      my_ulonglong num_rows;
++      struct ast_config *new;
++      struct ast_variable *cur_v, *new_v;
++      struct ast_category *cur_cat, *new_cat;
++      char sql[250] = "";
++      char last[80] = "";
++      int cat_started = 0;
++      int var_started = 0;
++      int last_cat_metric = 0;
++
++      last[0] = '\0';
++
++      if(!file || !strcmp(file, RES_CONFIG_MYSQL_CONF)) {
++              ast_log(LOG_WARNING, "MySQL RealTime: Cannot configure myself.\n");
++              return NULL;
++      }
++
++      snprintf(sql, sizeof(sql), "SELECT category, var_name, var_val, cat_metric FROM %s WHERE filename='%s' and commented=0 ORDER BY filename, cat_metric desc, var_metric asc, category, var_name, var_val, id", table, file);
++
++      ast_log(LOG_DEBUG, "MySQL RealTime: Static SQL: %s\n", sql);
++
++      /* We now have our complete statement; Lets connect to the server and execute it. */
++      ast_mutex_lock(&mysql_lock);
++      if(!mysql_reconnect(database)) {
++              ast_mutex_unlock(&mysql_lock);
++              return NULL;
++      }
++
++      if(mysql_real_query(&mysql, sql, strlen(sql))) {
++              ast_log(LOG_WARNING, "MySQL RealTime: Failed to query database. Check debug for more info.\n");
++              ast_log(LOG_DEBUG, "MySQL RealTime: Query: %s\n", sql);
++              ast_log(LOG_DEBUG, "MySQL RealTime: Query Failed because: %s\n", mysql_error(&mysql));
++              ast_mutex_unlock(&mysql_lock);
++              return NULL;
++      }
++
++      if((result = mysql_store_result(&mysql))) {
++              num_rows = mysql_num_rows(result);
++              ast_log(LOG_DEBUG, "MySQL RealTime: Found %llu rows.\n", num_rows);
++
++              /* There might exist a better way to access the column names other than counting,
++                   but I believe that would require another loop that we don't need. */
++
++              while((row = mysql_fetch_row(result))) {
++                      if(!strcmp(row[1], "#include")) {
++                              if (!ast_config_internal_load(row[2], cfg)) {
++                                      mysql_free_result(result);
++                                      ast_mutex_unlock(&mysql_lock);
++                                      return NULL;
++                              }
++                              continue;
++                      }
++
++                      if(strcmp(last, row[0]) || last_cat_metric != atoi(row[3])) {
++                              cur_cat = ast_category_new(row[0]);
++                              if (!cur_cat) {
++                                      ast_log(LOG_WARNING, "Out of memory!\n");
++                                      break;
++                              }
++                              strcpy(last, row[0]);
++                              last_cat_metric = atoi(row[3]);
++                              ast_category_append(cfg, cur_cat);
++                      }
++                      new_v = ast_variable_new(row[1], row[2]);
++                      ast_variable_append(cur_cat, new_v);
++              }
++      } else {
++              ast_log(LOG_WARNING, "MySQL RealTime: Could not find config '%s' in database.\n", file);
++      }
++
++      mysql_free_result(result);
++      ast_mutex_unlock(&mysql_lock);
++
++      return cfg;
++}
++
++static struct ast_config_engine mysql_engine = {
++      .name = "mysql",
++      .load_func = config_mysql,
++      .realtime_func = realtime_mysql,
++      .realtime_multi_func = realtime_multi_mysql,
++      .update_func = update_mysql
++};
++
++int load_module (void)
++{
++      parse_config();
++
++      ast_mutex_lock(&mysql_lock);
++
++      if(!mysql_reconnect(NULL)) {
++              ast_log(LOG_WARNING, "MySQL RealTime: Couldn't establish connection. Check debug.\n");
++              ast_log(LOG_DEBUG, "MySQL RealTime: Cannot Connect: %s\n", mysql_error(&mysql));
++      }
++
++      ast_config_engine_register(&mysql_engine);
++      if(option_verbose) {
++              ast_verbose("MySQL RealTime driver loaded.\n");
++      }
++      ast_cli_register(&cli_realtime_mysql_status);
++
++      ast_mutex_unlock(&mysql_lock);
++
++      return 0;
++}
++
++int unload_module (void)
++{
++      /* Aquire control before doing anything to the module itself. */
++      ast_mutex_lock(&mysql_lock);
++
++      mysql_close(&mysql);
++      ast_cli_unregister(&cli_realtime_mysql_status);
++      ast_config_engine_deregister(&mysql_engine);
++      if(option_verbose) {
++              ast_verbose("MySQL RealTime unloaded.\n");
++      }
++
++      STANDARD_HANGUP_LOCALUSERS;
++
++      /* Unlock so something else can destroy the lock. */
++      ast_mutex_unlock(&mysql_lock);
++
++      return 0;
++}
++
++int reload (void)
++{
++      /* Aquire control before doing anything to the module itself. */
++      ast_mutex_lock(&mysql_lock);
++
++      mysql_close(&mysql);
++      connected = 0;
++      parse_config();
++
++      if(!mysql_reconnect(NULL)) {
++              ast_log(LOG_WARNING, "MySQL RealTime: Couldn't establish connection. Check debug.\n");
++              ast_log(LOG_DEBUG, "MySQL RealTime: Cannot Connect: %s\n", mysql_error(&mysql));
++      }
++
++      ast_verbose(VERBOSE_PREFIX_2 "MySQL RealTime reloaded.\n");
++
++      /* Done reloading. Release lock so others can now use driver. */
++      ast_mutex_unlock(&mysql_lock);
++
++      return 0;
++}
++
++int parse_config (void)
++{
++      struct ast_config *config;
++      char *s;
++
++      config = ast_config_load(RES_CONFIG_MYSQL_CONF);
++
++      if(config) {
++              if(!(s=ast_variable_retrieve(config, "general", "dbuser"))) {
++                      ast_log(LOG_WARNING, "MySQL RealTime: No database user found, using 'asterisk' as default.\n");
++                      strncpy(dbuser, "asterisk", sizeof(dbuser) - 1);
++              } else {
++                      strncpy(dbuser, s, sizeof(dbuser) - 1);
++              }
++
++              if(!(s=ast_variable_retrieve(config, "general", "dbpass"))) {
++                        ast_log(LOG_WARNING, "MySQL RealTime: No database password found, using 'asterisk' as default.\n");
++                        strncpy(dbpass, "asterisk", sizeof(dbpass) - 1);
++                } else {
++                        strncpy(dbpass, s, sizeof(dbpass) - 1);
++                }
++
++              if(!(s=ast_variable_retrieve(config, "general", "dbhost"))) {
++                        ast_log(LOG_WARNING, "MySQL RealTime: No database host found, using localhost via socket.\n");
++                      dbhost[0] = '\0';
++                } else {
++                        strncpy(dbhost, s, sizeof(dbhost) - 1);
++                }
++
++              if(!(s=ast_variable_retrieve(config, "general", "dbname"))) {
++                        ast_log(LOG_WARNING, "MySQL RealTime: No database name found, using 'asterisk' as default.\n");
++                      strncpy(dbname, "asterisk", sizeof(dbname) - 1);
++                } else {
++                        strncpy(dbname, s, sizeof(dbname) - 1);
++                }
++
++              if(!(s=ast_variable_retrieve(config, "general", "dbport"))) {
++                        ast_log(LOG_WARNING, "MySQL RealTime: No database port found, using 3306 as default.\n");
++                      dbport = 3306;
++                } else {
++                      dbport = atoi(s);
++                }
++
++              if(dbhost && !(s=ast_variable_retrieve(config, "general", "dbsock"))) {
++                        ast_log(LOG_WARNING, "MySQL RealTime: No database socket found, using '/tmp/mysql.sock' as default.\n");
++                        strncpy(dbsock, "/tmp/mysql.sock", sizeof(dbsock) - 1);
++                } else {
++                        strncpy(dbsock, s, sizeof(dbsock) - 1);
++                }
++      }
++      ast_config_destroy(config);
++
++      if(dbhost) {
++              ast_log(LOG_DEBUG, "MySQL RealTime Host: %s\n", dbhost);
++              ast_log(LOG_DEBUG, "MySQL RealTime Port: %i\n", dbport);
++      } else {
++              ast_log(LOG_DEBUG, "MySQL RealTime Socket: %s\n", dbsock);
++      }
++      ast_log(LOG_DEBUG, "MySQL RealTime User: %s\n", dbuser);
++      ast_log(LOG_DEBUG, "MySQL RealTime Password: %s\n", dbpass);
++
++      return 1;
++}
++
++char *description (void)
++{
++      return res_config_mysql_desc;
++}
++
++int usecount (void)
++{
++      /* Try and get a lock. If unsuccessful, than that means another thread is using the mysql object. */
++      if(ast_mutex_trylock(&mysql_lock)) {
++              ast_log(LOG_DEBUG, "MySQL RealTime: Module usage count is 1.\n");
++              return 1;
++      }
++      ast_mutex_unlock(&mysql_lock);
++      return 0;
++}
++
++char *key ()
++{
++      return ASTERISK_GPL_KEY;
++}
++
++static int mysql_reconnect(const char *database)
++{
++      char my_database[50];
++
++      if(!database || ast_strlen_zero(database))
++              ast_copy_string(my_database, dbname, sizeof(my_database));
++      else
++              ast_copy_string(my_database, database, sizeof(my_database));
++
++      /* mutex lock should have been locked before calling this function. */
++
++      if((!connected) && (dbhost || dbsock) && dbuser && dbpass && my_database) {
++              if(!mysql_init(&mysql)) {
++                      ast_log(LOG_WARNING, "MySQL RealTime: Insufficient memory to allocate MySQL resource.\n");
++                      connected = 0;
++                      return 0;
++              }
++              if(mysql_real_connect(&mysql, dbhost, dbuser, dbpass, my_database, dbport, dbsock, 0)) {
++                      ast_log(LOG_DEBUG, "MySQL RealTime: Successfully connected to database.\n");
++                      connected = 1;
++                      connect_time = time(NULL);
++                      return 1;
++              } else {
++                      ast_log(LOG_ERROR, "MySQL RealTime: Failed to connect database server %s on %s. Check debug for more info.\n", dbname, dbhost);
++                      ast_log(LOG_DEBUG, "MySQL RealTime: Cannot Connect: %s\n", mysql_error(&mysql));
++                      connected = 0;
++                      return 0;
++              }
++      } else {
++              if(mysql_ping(&mysql) != 0) {
++                      connected = 0;
++                      ast_log(LOG_ERROR, "MySQL RealTime: Failed to reconnect. Check debug for more info.\n");
++                      ast_log(LOG_DEBUG, "MySQL RealTime: Server Error: %s\n", mysql_error(&mysql));
++                      return 0;
++              }
++
++              connected = 1;
++
++              if(mysql_select_db(&mysql, my_database) != 0) {
++                      ast_log(LOG_WARNING, "MySQL RealTime: Unable to select database: %s. Still Connected.\n", my_database);
++                      ast_log(LOG_DEBUG, "MySQL RealTime: Database Select Failed: %s\n", mysql_error(&mysql));
++                      return 0;
++              }
++
++              ast_log(LOG_DEBUG, "MySQL RealTime: Everything is fine.\n");
++              return 1;
++      }
++}
++
++static int realtime_mysql_status(int fd, int argc, char **argv)
++{
++      char status[256], status2[100] = "";
++      int ctime = time(NULL) - connect_time;
++
++      ast_mutex_lock(&mysql_lock);
++      if(mysql_reconnect(NULL)) {
++              if(dbhost) {
++                      snprintf(status, 255, "Connected to %s@%s, port %d", dbname, dbhost, dbport);
++              } else if(dbsock) {
++                      snprintf(status, 255, "Connected to %s on socket file %s", dbname, dbsock);
++              } else {
++                      snprintf(status, 255, "Connected to %s@%s", dbname, dbhost);
++              }
++
++              if(dbuser && *dbuser) {
++                      snprintf(status2, 99, " with username %s", dbuser);
++              }
++
++              if (ctime > 31536000) {
++                      ast_cli(fd, "%s%s for %d years, %d days, %d hours, %d minutes, %d seconds.\n", status, status2, ctime / 31536000, (ctime % 31536000) / 86400, (ctime % 86400) / 3600, (ctime % 3600) / 60, ctime % 60);
++              } else if (ctime > 86400) {
++                      ast_cli(fd, "%s%s for %d days, %d hours, %d minutes, %d seconds.\n", status, status2, ctime / 86400, (ctime % 86400) / 3600, (ctime % 3600) / 60, ctime % 60);
++              } else if (ctime > 3600) {
++                      ast_cli(fd, "%s%s for %d hours, %d minutes, %d seconds.\n", status, status2, ctime / 3600, (ctime % 3600) / 60, ctime % 60);
++              } else if (ctime > 60) {
++                      ast_cli(fd, "%s%s for %d minutes, %d seconds.\n", status, status2, ctime / 60, ctime % 60);
++              } else {
++                      ast_cli(fd, "%s%s for %d seconds.\n", status, status2, ctime);
++              }
++
++              ast_mutex_unlock(&mysql_lock);
++              return RESULT_SUCCESS;
++      } else {
++              ast_mutex_unlock(&mysql_lock);
++              return RESULT_FAILURE;
++      }
++}
diff --git a/src/patches/asterisk-1.2.4-ipfire-bristuff-0.3.0-PRE-1l.patch b/src/patches/asterisk-1.2.4-ipfire-bristuff-0.3.0-PRE-1l.patch
new file mode 100644 (file)
index 0000000..05aa370
--- /dev/null
@@ -0,0 +1,12853 @@
+diff -urN asterisk-1.2.4.orig/.version asterisk-1.2.4/.version
+--- asterisk-1.2.4.orig/.version       2006-01-31 04:55:50.000000000 +0100
++++ asterisk-1.2.4/.version    2006-01-31 09:41:43.000000000 +0100
+@@ -1 +1 @@
+-1.2.4
++1.2.4-BRIstuffed-0.3.0-PRE-1l-for-ipfire
+diff -urN asterisk-1.2.4.orig/HARDWARE asterisk-1.2.4/HARDWARE
+--- asterisk-1.2.4.orig/HARDWARE       2005-11-29 19:24:39.000000000 +0100
++++ asterisk-1.2.4/HARDWARE    2006-01-31 09:41:43.000000000 +0100
+@@ -37,6 +37,19 @@
+    * Wildcard TE410P - Quad T1/E1 switchable interface.  Supports PRI and 
+      RBS signalling, as well as PPP, FR, and HDLC data modes.
++-- Junghanns.NET (Primary author of BRIstuff)
++      http://www.junghanns.net
++      
++    * quadBRI PCI ISDN - 4port BRI ISDN interface, supports NT and TE mode
++    
++    * octoBRI PCI ISDN - 8port BRI ISDN interface, supports NT and TE mode
++
++    * singleE1 PCI ISDN - Single E1 interface
++
++    * doubleE1 PCI ISDN - Double E1 interface
++    
++    * quadGSM PCI ISDN - 4 channel GSM interface
++
+ Non-zaptel compatible hardware
+ ==============================
+diff -urN asterisk-1.2.4.orig/LICENSE asterisk-1.2.4/LICENSE
+--- asterisk-1.2.4.orig/LICENSE        2005-11-29 19:24:39.000000000 +0100
++++ asterisk-1.2.4/LICENSE     2006-01-31 09:41:43.000000000 +0100
+@@ -1,7 +1,7 @@
+-Asterisk is distributed under the GNU General Public License version 2
+-and is also available under alternative licenses negotiated directly
+-with Digium, Inc. If you obtained Asterisk under the GPL, then the GPL
+-applies to all loadable Asterisk modules used on your system as well,
++BRIstuffed Asterisk is distributed under the GNU General Public License version 2
++and is not available under any alternative licenses.
++If you obtained BRIstuffed Asterisk under the GPL, then the GPL
++applies to all loadable BRIstuffed Asterisk modules used on your system as well,
+ except as defined below. The GPL (version 2) is included in this
+ source tree in the file COPYING.
+diff -urN asterisk-1.2.4.orig/Makefile asterisk-1.2.4/Makefile
+--- asterisk-1.2.4.orig/Makefile       2005-12-05 07:47:51.000000000 +0100
++++ asterisk-1.2.4/Makefile    2006-01-31 09:41:43.000000000 +0100
+@@ -759,6 +759,9 @@
+               echo ";astctlowner = root" ; \
+               echo ";astctlgroup = apache" ; \
+               echo ";astctl = asterisk.ctl" ; \
++              echo "[options]" ; \
++              echo "uniquename = asterisk" ;\
++              echo "silence_suppression = yes" ;\
+               ) > $(DESTDIR)$(ASTCONFPATH) ; \
+       else \
+               echo "Skipping asterisk.conf creation"; \
+diff -urN asterisk-1.2.4.orig/README asterisk-1.2.4/README
+--- asterisk-1.2.4.orig/README 2005-11-29 19:24:39.000000000 +0100
++++ asterisk-1.2.4/README      2006-01-31 09:41:43.000000000 +0100
+@@ -4,6 +4,8 @@
+ Copyright (C) 2001-2005 Digium, Inc.
+ and other copyright holders.
++Copyright (C) 2002-2005 Junghanns.NET GmbH 
++and other copyright holders.
+ ================================================================
+ * SECURITY
+diff -urN asterisk-1.2.4.orig/README.chan_capi asterisk-1.2.4/README.chan_capi
+--- asterisk-1.2.4.orig/README.chan_capi       1970-01-01 01:00:00.000000000 +0100
++++ asterisk-1.2.4/README.chan_capi    2006-01-31 09:41:43.000000000 +0100
+@@ -0,0 +1,146 @@
++(CAPI*) chan_capi a Common ISDN API 2.0 implementation for Asterisk
++(C) 2002, 2003, 2004, 2005 Junghanns.NET GmbH 
++Klaus-Peter Junghanns <kpj@junghanns.net>
++
++This program is free software and may be modified and distributed under
++the terms of the GNU Public License. There is _NO_ warranty for this!
++
++Thanks go to the debuggers and bugfixers (listed in chronological order) :)
++===========================================================================
++Lele Forzani <lele@windmill.it>
++Florian Overkamp <florian@obsimref.com>
++Gareth Watts <gareth@omnipotent.net>
++Jeff Noxon <jeff@planetfall.com>
++Petr Michalek <petr.michalek@aca.cz>
++Jan Stocker
++(...and all the others that i forgot..) :-)
++
++chan_capi version 0.4.0-PRE1 includes:
++======================================
++
++- multiple controller support
++- CID,DNID (callling party, called party)
++- CLIR/CLIP
++- supplementary services, CD,HOLD,RETRIEVE,ECT
++- DTMF (dependend on card) + software DTMF support
++- early B3 connects (always,success,never)
++- digital audio (what did you think?)
++- incoming/outgoing calls
++- overlap sending (dialtone)
++- E(xplicit) C(all) T(ransfer) (...although it's done implicit .. but dont tell!)
++- tuneable latency ;) you can configure the size of B3 blocks at compile time
++  (in chan_capi_pvt.h, AST_CAPI_MAX_B3_BLOCK_SIZE)
++  the default is 160 samples, for non-VoIP use you can tune it down to 130
++- use asterisk's internal dsp functions for dtmf
++- alaw support 
++- ulaw support! 
++- Eicon CAPI echo cancelation (echocancel=1)
++- reject call waiting (ACO)
++- DID for Point to Point mode (a.k.a overlap receiving)
++- experimental echo squelching (echosquelch=1)
++- call progress, no need to add ||r to your dialstring anymore
++- rx/tx gains (rxgain=1.0)
++- call deflection on circuitbusy (makefile option) (deflect=12345678)
++- (inter)national dialing prefix (for callerid) configurable in capi.conf
++- CLI command "capi info" shows B channel status
++- capiECT will announce the callerID since it gets lost on most isdn pbxes
++  the called party can press # to drop the call
++- audio syncing (timing outgoing dataB3 on incoming dataB3), supposed to fix
++  the DATA_B3_REQ (error = 0x1103) problem
++- catch all MSN (incomingmsn=*)
++- some configuration enhancements (msn=123,124,125 and controller=1,2,3,4)
++- accountcode= added.
++- finally the echo squelching works!
++- callgroup support
++- fixed pipe leak
++- updated to support the new frame->delivery field
++- compiles with latest cvs with a makefile option (LOOK AT THE MAKEFILE)
++- fixed channel name bug in p2p mode
++- added app_capiNoES for disabling the primitive echo suppressor, use this before
++  you start recording voicemail or your files may get choppy
++- fixed for latest cvs (AST_MUTEX_DEFINE_STATIC)
++- fixed for latest cvs (asterisk/parking.h -> asterisk/features.h)
++- fixed for latest cvs ast_pthread_create
++
++- ATTENTION! the dialstring syntax now uses the zaptel dialstring syntax 
++  it used to be:  Dial(CAPI/[@]<outgoingMSN>:[b|B]<destination>)
++ 
++  now it is:      Dial(CAPI/g<group>/[b|B]<destination>)
++  or:             Dial(CAPI/contr<controller>/[b|B]<destination>)
++ 
++  CLIP/CLIR is now uses the calling presentation of the calling channel, this can
++  be modified using the CallingPres() application. Use CallinPres(32) for CLIR.
++  That is why the msn= param in capi.conf is now obsolete. The callerID is also
++  taken from the calling channel.
++
++- fixes for BSD (Jan Stocker)
++
++Helper applications
++===================
++kapejod says: "No No No, dont use those yet....!" (except maybe HOLD,ECT...)
++
++app_capiCD.c          forwards an unanswered call to another phone (does not rely on sservice CD)
++                      example:
++                      exten => s,1,Wait,1
++                      exten => s,2,capiCD,12345678
++                      
++app_capiHOLD.c                puts an answered call on hold, this has nothing to do with asterisk's onhold thingie (music et al)
++                      after putting a call onhold, never use the Wait application!
++
++app_capiRETRIEVE.c    gets the holded call back
++
++app_capiECT.c         explicit call transfer of the holded call (must put call on hold first!)
++                      example:
++                      exten => s,1,Answer
++                      exten => s,2,capiHOLD
++                      exten => s,3,capiECT,55:50
++                      will ECT the call to 50 using 55 as the callerid/outgoing msn
++
++
++Using CLIR
++==========
++Use the CallingPres() application before you dial:
++exten => _X.,1,CallingPres(32)
++exten => _X.,2,Dial(CAPI/contr1/${EXTEN})    
++
++Enjoying early B3 connects (inband call progress, tones and announcements)
++==========================================================================
++early B3 is now configurable in the dialstring :)
++if you prefix the destination number with a 'b' early B3 will always be used, also if the call fails
++because the number is unprovisioned, etc ...
++if you prefix it with a 'B' early B3 will only be used on successful calls, giving you ring indication,etc...
++
++dont use indications in the Dial command, your local exchange will do that for you:
++exten => _X.,1,Dial(CAPI/contr1/B${EXTEN},30)         (early B3 on success)
++exten => _X.,1,Dial(CAPI/contr1/b${EXTEN},30)         (always early B3)
++exten => _X.,1,Dial(CAPI/contr1/${EXTEN},30,r)                (no early B3, fake ring indication)
++
++exten => _X.,1,Dial(CAPI/contr1/b${EXTEN},30,r)               (always early B3, fake indicatons if the exchange
++                                                      does not give us indications)
++exten => _X.,1,Dial(CAPI/contr1/B${EXTEN},30,r)               (early B3 on success, fake indicatons if the exchange
++                                                      does not give us indications)
++    
++you can totally turn B3 off in the Makefile at buildtime (-DNEVER_EVER_EARLY_B3_CONNECTS).
++
++For normal PBX usage you would use the "b" option, always early B3.
++
++Overlap sending (a.k.a. real dialtone)
++======================================
++when you dial an empty number, and have early B3 enabled, with:
++    Dial(CAPI/g1/b)
++the channel will come up at once and give you the dialtone it gets from the local exchange.
++at this point the channel is like a legacy phone, now you can send dtmf digits to dial.    
++
++Example context for incoming calls on MSN 12345678:
++===================================================
++
++[capi-in]
++exten => 12345678,1,Dial(SIP/phone1)
++exten => 12345678,2,Hangup
++
++
++More information/documentation and commercial support can be found at:
++      http://www.junghanns.net/asterisk/
++      
++
++
+diff -urN asterisk-1.2.4.orig/agi/Makefile asterisk-1.2.4/agi/Makefile
+--- asterisk-1.2.4.orig/agi/Makefile   2005-11-29 19:24:39.000000000 +0100
++++ asterisk-1.2.4/agi/Makefile        2006-01-31 09:41:43.000000000 +0100
+@@ -11,7 +11,7 @@
+ # the GNU General Public License
+ #
+-AGIS=agi-test.agi eagi-test eagi-sphinx-test
++AGIS=agi-test.agi eagi-test eagi-sphinx-test xagi-test
+ CFLAGS+=
+@@ -37,7 +37,7 @@
+       $(CC) $(CFLAGS) -o eagi-sphinx-test eagi-sphinx-test.o $(LIBS) 
+ clean:
+-      rm -f *.so *.o look .depend eagi-test eagi-sphinx-test
++      rm -f *.so *.o look .depend eagi-test eagi-sphinx-test xagi-test
+ %.so : %.o
+       $(CC) -shared -Xlinker -x -o $@ $<
+diff -urN asterisk-1.2.4.orig/agi/xagi-test.c asterisk-1.2.4/agi/xagi-test.c
+--- asterisk-1.2.4.orig/agi/xagi-test.c        1970-01-01 01:00:00.000000000 +0100
++++ asterisk-1.2.4/agi/xagi-test.c     2006-01-31 09:41:43.000000000 +0100
+@@ -0,0 +1,176 @@
++/*
++ * Asterisk -- A telephony toolkit for Linux.
++ *
++ * XAGI sample script 
++ * 
++ * Copyright (C) 2005 Junghanns.NET GmbH
++ * Klaus-Peter Junghanns <kpj@junghanns.net>
++ *
++ * based on eagi-test.c
++ *
++ * This program is free software, distributed under the terms of
++ * the GNU General Public License
++ */
++
++#include <stdio.h>
++#include <unistd.h>
++#include <stdlib.h>
++#include <errno.h>
++#include <string.h>
++#include <sys/select.h>
++#ifdef SOLARIS
++#include <solaris-compat/compat.h>
++#endif
++
++#define AUDIO_FILENO_IN (STDERR_FILENO + 1)
++#define AUDIO_FILENO_OUT (STDERR_FILENO + 2)
++
++static int read_environment(void)
++{
++      char buf[256];
++      char *val;
++      /* Read environment */
++      for(;;) {
++              fgets(buf, sizeof(buf), stdin);
++              if (feof(stdin))
++                      return -1;
++              buf[strlen(buf) - 1] = '\0';
++              /* Check for end of environment */
++              if (!strlen(buf))
++                      return 0;
++              val = strchr(buf, ':');
++              if (!val) {
++                      fprintf(stderr, "Invalid environment: '%s'\n", buf);
++                      return -1;
++              }
++              *val = '\0';
++              val++;
++              val++;
++              /* Skip space */
++      //      fprintf(stderr, "Environment: '%s' is '%s'\n", buf, val);
++
++              /* Load into normal environment */
++              setenv(buf, val, 1);
++              
++      }
++      /* Never reached */
++      return 0;
++}
++
++static void app_echo(void)
++{
++      fd_set fds;
++      int res;
++      int bytes = 0;
++      static char astresp[256];
++      char audiobuf[16000]; /* 1 second of audio */
++      for (;;) {
++              FD_ZERO(&fds);
++              FD_SET(STDIN_FILENO, &fds);
++              FD_SET(AUDIO_FILENO_IN, &fds);
++              /* Wait for *some* sort of I/O */
++              res = select(AUDIO_FILENO_IN + 1, &fds, NULL, NULL, NULL);
++              if (res < 0) {
++                      fprintf(stderr, "Error in select: %s\n", strerror(errno));
++                      return;
++              }
++              if (FD_ISSET(STDIN_FILENO, &fds)) {
++                      fgets(astresp, sizeof(astresp), stdin);
++                      if (feof(stdin)) {
++                              return NULL;
++                      }
++                      astresp[strlen(astresp) - 1] = '\0';
++                      fprintf(stderr, "Ooh, got a response from Asterisk: '%s'\n", astresp);
++                      return astresp;
++              }
++              if (FD_ISSET(AUDIO_FILENO_IN, &fds)) {
++                      /* what goes in.... */
++                      res = read(AUDIO_FILENO_IN, audiobuf, sizeof(audiobuf));
++                      if (res > 0) {
++                          bytes = res;
++                          /* must come out */
++                          write(AUDIO_FILENO_OUT, audiobuf, bytes);
++                      }
++              }
++      }
++}
++
++static char *wait_result(void)
++{
++      fd_set fds;
++      int res;
++      int bytes = 0;
++      static char astresp[256];
++      char audiobuf[4096];
++      for (;;) {
++              FD_ZERO(&fds);
++              FD_SET(STDIN_FILENO, &fds);
++              FD_SET(AUDIO_FILENO_IN, &fds);
++              /* Wait for *some* sort of I/O */
++              res = select(AUDIO_FILENO_IN + 1, &fds, NULL, NULL, NULL);
++              if (res < 0) {
++                      fprintf(stderr, "Error in select: %s\n", strerror(errno));
++                      return NULL;
++              }
++              if (FD_ISSET(STDIN_FILENO, &fds)) {
++                      fgets(astresp, sizeof(astresp), stdin);
++                      if (feof(stdin)) {
++                              fprintf(stderr, "Got hungup on apparently\n");
++                              return NULL;
++                      }
++                      astresp[strlen(astresp) - 1] = '\0';
++                      fprintf(stderr, "Ooh, got a response from Asterisk: '%s'\n", astresp);
++                      return astresp;
++              }
++              if (FD_ISSET(AUDIO_FILENO_IN, &fds)) {
++                      res = read(AUDIO_FILENO_IN, audiobuf, sizeof(audiobuf));
++                      /* drop it, like it's hot */
++              }
++      }
++              
++}
++
++static char *run_command(char *command)
++{
++      fprintf(stdout, "%s\n", command);
++      return wait_result();
++}
++
++
++static int run_script(void)
++{
++      char *res;
++              res = run_command("STREAM FILE demo-echotest \"\"");
++      if (!res) {
++              fprintf(stderr, "Failed to execute command\n");
++              return -1;
++      }
++      app_echo();
++      return 0;
++}
++
++int main(int argc, char *argv[])
++{
++      char *tmp;
++      int ver = 0;
++      int subver = 0;
++      /* Setup stdin/stdout for line buffering */
++      setlinebuf(stdin);
++      setlinebuf(stdout);
++      if (read_environment()) {
++              fprintf(stderr, "Failed to read environment: %s\n", strerror(errno));
++              exit(1);
++      }
++      tmp = getenv("agi_enhanced");
++      if (tmp) {
++              if (sscanf(tmp, "%d.%d", &ver, &subver) != 2)
++                      ver = 0;
++      }
++      if (ver < 2) {
++              fprintf(stderr, "No XAGI services available.  Use XAGI, not AGI or EAGI\n");
++              exit(1);
++      }
++      if (run_script())
++              return -1;
++      exit(0);
++}
+diff -urN asterisk-1.2.4.orig/apps/Makefile asterisk-1.2.4/apps/Makefile
+--- asterisk-1.2.4.orig/apps/Makefile  2005-11-29 19:24:39.000000000 +0100
++++ asterisk-1.2.4/apps/Makefile       2006-01-31 09:41:43.000000000 +0100
+@@ -28,8 +28,15 @@
+      app_test.so app_forkcdr.so app_math.so app_realtime.so \
+      app_dumpchan.so app_waitforsilence.so app_while.so app_setrdnis.so \
+      app_md5.so app_readfile.so app_chanspy.so app_settransfercapability.so \
++     app_pickup.so app_segfault.so app_callingpres.so app_devstate.so \
+      app_dictate.so app_externalivr.so app_directed_pickup.so \
+-     app_mixmonitor.so app_stack.so
++     app_mixmonitor.so app_stack.so 
++
++
++ifneq ($(wildcard $(CROSS_COMPILE_TARGET)/usr/include/capi20.h)$(wildcard $(CROSS_COMPILE_TARGET)/usr/local/include/capi20.h),)
++  APPS+= app_capiNoES.so app_capiCD.so app_capiECT.so
++endif
++    
+ #
+ # Obsolete things...
+diff -urN asterisk-1.2.4.orig/apps/app_callingpres.c asterisk-1.2.4/apps/app_callingpres.c
+--- asterisk-1.2.4.orig/apps/app_callingpres.c 1970-01-01 01:00:00.000000000 +0100
++++ asterisk-1.2.4/apps/app_callingpres.c      2006-01-31 09:41:43.000000000 +0100
+@@ -0,0 +1,70 @@
++/*
++ * An application to change the CallingPresentation for an Asterisk channel.
++ *
++ * Copyright (C) 2005 Junghanns.NET GmbH
++ * Klaus-Peter Junghanns <kpj@junghanns.net>
++ *
++ * This program is free software, distributed under the terms of
++ * the GNU General Public License. 
++ *
++ */
++
++#include <stdlib.h>
++#include <unistd.h>
++#include <string.h>
++#include <stdio.h>
++#include <asterisk/lock.h>
++#include <asterisk/file.h>
++#include <asterisk/logger.h>
++#include <asterisk/channel.h>
++#include <asterisk/pbx.h>
++#include <asterisk/module.h>
++
++static char *synopsis_callingpres = "Change the presentation for the callerid";
++static char *descrip_callingpres = "Callingpres(number): Changes the presentation for the callerid. Should be called before placing an outgoing call\n";
++static char *app_callingpres = "CallingPres";
++STANDARD_LOCAL_USER;
++LOCAL_USER_DECL;
++
++
++static int change_callingpres(struct ast_channel *chan, void *data)
++{
++    int mode = 0;
++    struct localuser *u;
++    LOCAL_USER_ADD(u);
++    if (data) {
++        mode = atoi((char *)data);
++        chan->cid.cid_pres = mode;
++    } else
++        ast_log(LOG_NOTICE, "Application %s requres an argument: %s(number)\n", app_callingpres,app_callingpres);
++    LOCAL_USER_REMOVE(u);
++    return 0;
++}    
++
++int unload_module(void)
++{
++    STANDARD_HANGUP_LOCALUSERS;
++    return ast_unregister_application(app_callingpres);
++}
++
++int load_module(void)
++{
++    return ast_register_application(app_callingpres, change_callingpres, synopsis_callingpres, descrip_callingpres);
++}
++
++char *description(void)
++{
++    return descrip_callingpres;
++}
++
++int usecount(void)
++{
++    int res;
++    STANDARD_USECOUNT(res);
++    return res;
++}
++
++char *key()
++{
++    return ASTERISK_GPL_KEY;
++}
+diff -urN asterisk-1.2.4.orig/apps/app_capiCD.c asterisk-1.2.4/apps/app_capiCD.c
+--- asterisk-1.2.4.orig/apps/app_capiCD.c      1970-01-01 01:00:00.000000000 +0100
++++ asterisk-1.2.4/apps/app_capiCD.c   2006-01-31 09:41:43.000000000 +0100
+@@ -0,0 +1,172 @@
++/*
++ * (CAPI*)
++ *
++ * An implementation of Common ISDN API 2.0 for Asterisk
++ *
++ * Call Deflection, inspired by capircvd by Alexander Brickwedde
++ *
++ * Copyright (C) 2002,2003,2004,2005 Junghanns.NET GmbH
++ *
++ * Klaus-Peter Junghanns <kapejod@ns1.jnetdns.de>
++ *
++ * This program is free software and may be modified and 
++ * distributed under the terms of the GNU Public License.
++ */
++
++#include <stdlib.h>
++#include <unistd.h>
++#include <string.h>
++#include <stdio.h>
++#include <linux/capi.h>
++#include <capi20.h>
++
++#include <asterisk/file.h>
++#include <asterisk/logger.h>
++#include <asterisk/channel.h>
++#include <asterisk/pbx.h>
++#include <asterisk/module.h>
++#include <asterisk/chan_capi.h>
++#include <asterisk/chan_capi_app.h>
++
++
++
++static char *tdesc = "(CAPI*) Call Deflection, the magic thing.";
++static char *app = "capiCD";
++static char *synopsis = "call deflection";
++
++STANDARD_LOCAL_USER;
++
++LOCAL_USER_DECL;
++
++static int capiCD_exec(struct ast_channel *chan, void *data)
++{
++    struct ast_capi_pvt *i = chan->tech_pvt;
++    MESSAGE_EXCHANGE_ERROR Info;
++    _cmsg     CMSG;
++    char      bchaninfo[1];
++    char      fac[60];
++    int res=0;
++    int ms=3000;
++    struct localuser *u;
++
++    if (!data) {
++      ast_log(LOG_WARNING, "cd requires an argument (destination phone number)\n");
++      return -1;
++    }
++    LOCAL_USER_ADD(u);
++    /* Do our thing here */
++
++    if ((i->state == CAPI_STATE_CONNECTED) || (i->state == CAPI_STATE_BCONNECTED)) {
++      ast_log(LOG_ERROR, "call deflection does not work with calls that are already connected!\n");
++      LOCAL_USER_REMOVE(u);
++      return -1;
++    }
++    // wait until the channel is alerting, so we dont drop the call and interfer with msgs
++    while ((ms > 0) && (i->state != CAPI_STATE_ALERTING)) {
++      sleep(100);
++      ms -= 100;
++    }
++
++    // make sure we hang up correctly
++    i->state = CAPI_STATE_CONNECTPENDING;
++
++    fac[0]=0; // len 
++    fac[1]=0; //len 
++    fac[2]=0x01; // Use D-Chan
++    fac[3]=0; // Keypad len
++    fac[4]=31;        // user user data? len = 31 = 29 + 2
++    fac[5]=0x1c;      // magic?
++    fac[6]=0x1d;      // strlen destination + 18 = 29
++    fac[7]=0x91;      // ..
++    fac[8]=0xA1;
++    fac[9]=0x1A;      // strlen destination + 15 = 26
++    fac[10]=0x02;
++    fac[11]=0x01;
++    fac[12]=0x70;
++    fac[13]=0x02;
++    fac[14]=0x01;
++    fac[15]=0x0d;
++    fac[16]=0x30;
++    fac[17]=0x12;     // strlen destination + 7 = 18
++    fac[18]=0x30;     // ...hm 0x30
++    fac[19]=0x0d;     // strlen destination + 2       
++    fac[20]=0x80;     // CLIP
++    fac[21]=0x0b;     //  strlen destination 
++    fac[22]=0x01;     //  destination start
++    fac[23]=0x01;     //  
++    fac[24]=0x01;     //  
++    fac[25]=0x01;     //  
++    fac[26]=0x01;     //  
++    fac[27]=0x01;     //  
++    fac[28]=0x01;     //  
++    fac[29]=0x01;     //  
++    fac[30]=0x01;     //  
++    fac[31]=0x01;     //  
++    fac[32]=0x01;     //  
++    fac[33]=0x01;     // 0x1 = sending complete
++    fac[34]=0x01;
++    fac[35]=0x01;
++                                 
++    memcpy((unsigned char *)fac+22,data,strlen(data));
++    fac[22+strlen(data)]=0x01;        // fill with 0x01 if number is only 6 numbers (local call)
++    fac[23+strlen(data)]=0x01;
++    fac[24+strlen(data)]=0x01;
++    fac[25+strlen(data)]=0x01;
++    fac[26+strlen(data)]=0x01;
++     
++    fac[6]=18+strlen(data);
++    fac[9]=15+strlen(data);
++    fac[17]=7+strlen(data);
++    fac[19]=2+strlen(data);
++    fac[21]=strlen(data);
++
++    bchaninfo[0] = 0x1;
++    INFO_REQ_HEADER(&CMSG,ast_capi_ApplID,ast_capi_MessageNumber++,0);
++    INFO_REQ_CONTROLLER(&CMSG) = i->controller;
++    INFO_REQ_PLCI(&CMSG) = i->PLCI;
++    INFO_REQ_BCHANNELINFORMATION(&CMSG) = (unsigned char*)bchaninfo; // use D-Channel
++    INFO_REQ_KEYPADFACILITY(&CMSG) = 0;
++    INFO_REQ_USERUSERDATA(&CMSG) = 0;
++    INFO_REQ_FACILITYDATAARRAY(&CMSG) = (unsigned char*) fac + 4;
++
++    if ((Info = _capi_put_cmsg(&CMSG)) != 0) {
++      ast_log(LOG_ERROR,"Error sending INFO_REQ\n");
++      return Info;
++    } else {
++      if (capidebug) {
++          // ast_log(LOG_NOTICE,"%s\n",capi_cmsg2str(&CMSG));
++          ast_log(LOG_NOTICE,"sent INFO_REQ PLCI = %#x\n",i->PLCI);
++      }
++    }
++
++    LOCAL_USER_REMOVE(u);
++    return res;
++}
++
++int unload_module(void)
++{
++      STANDARD_HANGUP_LOCALUSERS;
++      return ast_unregister_application(app);
++}
++
++int load_module(void)
++{
++      return ast_register_application(app, capiCD_exec,synopsis,tdesc);
++}
++
++char *description(void)
++{
++      return tdesc;
++}
++
++int usecount(void)
++{
++      int res;
++      STANDARD_USECOUNT(res);
++      return res;
++}
++
++char *key()
++{
++      return ASTERISK_GPL_KEY;
++}
+diff -urN asterisk-1.2.4.orig/apps/app_capiECT.c asterisk-1.2.4/apps/app_capiECT.c
+--- asterisk-1.2.4.orig/apps/app_capiECT.c     1970-01-01 01:00:00.000000000 +0100
++++ asterisk-1.2.4/apps/app_capiECT.c  2006-01-31 09:41:43.000000000 +0100
+@@ -0,0 +1,210 @@
++/*
++ * (CAPI*)
++ *
++ * An implementation of Common ISDN API 2.0 for Asterisk
++ *
++ * ECT transfer the held call 
++ *
++ * Copyright (C) 2002,2003,2004,2005 Junghanns.NET GmbH
++ *
++ * Klaus-Peter Junghanns <kapejod@ns1.jnetdns.de>
++ *
++ * This program is free software and may be modified and 
++ * distributed under the terms of the GNU Public License.
++ */
++
++#include <stdlib.h>
++#include <unistd.h>
++#include <string.h>
++#include <stdio.h>
++#include <linux/capi.h>
++#include <capi20.h>
++#include <asterisk/file.h>
++#include <asterisk/logger.h>
++#include <asterisk/channel.h>
++#include <asterisk/pbx.h>
++#include <asterisk/module.h>
++#include <asterisk/say.h>
++#include <asterisk/chan_capi.h>
++#include <asterisk/chan_capi_app.h>
++
++
++static char *tdesc = "(CAPI*) ECT";
++static char *app = "capiECT";
++static char *synopsis = "transfer the call that is on hold";
++
++STANDARD_LOCAL_USER;
++
++LOCAL_USER_DECL;
++
++
++static int capiECT_exec(struct ast_channel *chan, void *data)
++{
++    struct ast_capi_pvt *i = chan->tech_pvt;
++    MESSAGE_EXCHANGE_ERROR Info;
++    _cmsg     CMSG;
++    unsigned char fac[8];
++    int res=0;
++    struct localuser *u;
++    char *ecodes = "*#";
++
++    if (!data) {
++      ast_log(LOG_WARNING, "ECT requires an argument (destination phone number)\n");
++      return -1;
++    }
++    LOCAL_USER_ADD(u);
++    /* Do our thing here */
++    if (i->onholdPLCI <= 0) {
++      ast_log(LOG_WARNING, "no call on hold that could be transfered\n");
++      return -1;
++    }
++
++    ast_log(LOG_NOTICE,"ECT to %s\n",(char *)data);
++    capi_call(chan,data,0);
++
++    while ((i->state != CAPI_STATE_BCONNECTED) && (i->onholdPLCI != 0)) {
++      usleep(10000);
++    }
++
++
++    if (i->state == CAPI_STATE_BCONNECTED) {
++      ast_log(LOG_NOTICE,"call was answered\n");
++
++      capi_detect_dtmf(chan,1);
++
++      // put the stuff to play announcement message here --->   <-----
++      res = ast_say_digit_str(chan,i->cid,ecodes,chan->language);
++      if ( res == '#') {
++          ast_log(LOG_NOTICE,"res = %d\n",res);
++          // user pressed #, hangup
++              // first the holded user
++//            ast_exec("capiRETRIEVE",chan);
++
++              DISCONNECT_REQ_HEADER(&CMSG, ast_capi_ApplID, ast_capi_MessageNumber++, 0);
++              DISCONNECT_REQ_PLCI(&CMSG) = i->onholdPLCI;
++
++              if ((Info = _capi_put_cmsg(&CMSG)) != 0) {
++                  ast_log(LOG_NOTICE, "error sending DISCONNECT_REQ PLCI=%#x\n",i->onholdPLCI);
++              } else {
++                  ast_log(LOG_NOTICE, "sent DISCONNECT_REQ PLCI=%#x\n",i->onholdPLCI);
++              }
++              
++              // then the destination
++
++              DISCONNECT_B3_REQ_HEADER(&CMSG, ast_capi_ApplID, ast_capi_MessageNumber++, 0);
++              DISCONNECT_B3_REQ_NCCI(&CMSG) = i->NCCI;
++
++              if ((Info = _capi_put_cmsg(&CMSG)) != 0) {
++                  ast_log(LOG_NOTICE, "error sending DISCONNECT_B3_REQ NCCI=%#x\n",i->NCCI);
++              } else {
++                  ast_log(LOG_NOTICE, "sent DISCONNECT_B3_REQ NCCI=%#x\n",i->NCCI);
++              }
++
++              // wait for the B3 layer to go down
++              while (i->state != CAPI_STATE_CONNECTED) {
++                  usleep(10000);
++              }
++
++              DISCONNECT_REQ_HEADER(&CMSG, ast_capi_ApplID, ast_capi_MessageNumber++, 0);
++              DISCONNECT_REQ_PLCI(&CMSG) = i->PLCI;
++
++              if ((Info = _capi_put_cmsg(&CMSG)) != 0) {
++                  ast_log(LOG_NOTICE, "error sending DISCONNECT_REQ PLCI=%#x\n",i->PLCI);
++              } else {
++                  ast_log(LOG_NOTICE, "sent DISCONNECT_REQ PLCI=%#x\n",i->PLCI);
++              }
++              
++              
++              LOCAL_USER_REMOVE(u);
++              return -1;
++
++      } else {
++          // now drop the bchannel
++          DISCONNECT_B3_REQ_HEADER(&CMSG, ast_capi_ApplID, ast_capi_MessageNumber++, 0);
++          DISCONNECT_B3_REQ_NCCI(&CMSG) = i->NCCI;
++
++          if ((Info = _capi_put_cmsg(&CMSG)) != 0) {
++              ast_log(LOG_NOTICE, "error sending DISCONNECT_B3_REQ NCCI=%#x\n",i->NCCI);
++          } else {
++              ast_log(LOG_NOTICE, "sent DISCONNECT_B3_REQ NCCI=%#x\n",i->NCCI);
++          }
++
++          // wait for the B3 layer to go down
++          while (i->state != CAPI_STATE_CONNECTED) {
++              usleep(10000);
++          } 
++      }
++    }
++
++    // the caller onhold hungup or died away, drop the answered call
++    if (i->onholdPLCI == 0) {
++      DISCONNECT_REQ_HEADER(&CMSG, ast_capi_ApplID, ast_capi_MessageNumber++, 0);
++      DISCONNECT_REQ_PLCI(&CMSG) = i->PLCI;
++
++      if ((Info = _capi_put_cmsg(&CMSG)) != 0) {
++          ast_log(LOG_NOTICE, "error sending DISCONNECT_REQ PLCI=%#x\n",i->PLCI);
++      } else {
++          ast_log(LOG_NOTICE, "sent DISCONNECT_REQ PLCI=%#x\n",i->PLCI);
++      }
++      return -1;
++    }
++
++    ast_log(LOG_NOTICE,"onholdPLCI = %d\n",i->onholdPLCI);
++
++
++    fac[0] = 7;       // len
++    fac[1] = 0x06; // ECT (function)
++    fac[2] = 0x00;
++    fac[3] = 4; //len //sservice specific parameter , cstruct
++    fac[4] = (i->onholdPLCI << 8 ) >> 8;
++    fac[5] = i->onholdPLCI >> 8;
++    fac[6] = 0;
++    fac[7] = 0;
++
++    FACILITY_REQ_HEADER(&CMSG,ast_capi_ApplID,ast_capi_MessageNumber++,0);
++    FACILITY_REQ_CONTROLLER(&CMSG) = i->controller;
++    FACILITY_REQ_PLCI(&CMSG) = i->onholdPLCI;
++    FACILITY_REQ_FACILITYSELECTOR(&CMSG) = 0x0003; // sservices
++    FACILITY_REQ_FACILITYREQUESTPARAMETER(&CMSG) = (unsigned char *)&fac;
++
++    if ((Info = _capi_put_cmsg(&CMSG)) != 0) {
++      ast_log(LOG_ERROR,"Error sending FACILITY_REQ\n");
++      return Info;
++    } else {
++      ast_log(LOG_NOTICE,"sent FACILITY_REQ PLCI = %#x (%#x %#x) onholdPLCI = %#x\n ",i->PLCI,fac[4],fac[5],i->onholdPLCI);
++      ast_log(LOG_NOTICE,"%s\n",capi_cmsg2str(&CMSG));
++    }
++
++//    i->outgoing = -1; // incoming + outgoing, this is a magic channel :)
++
++    LOCAL_USER_REMOVE(u);
++    return res;
++}
++
++int unload_module(void)
++{
++      STANDARD_HANGUP_LOCALUSERS;
++      return ast_unregister_application(app);
++}
++
++int load_module(void)
++{
++      return ast_register_application(app, capiECT_exec,synopsis,tdesc);
++}
++
++char *description(void)
++{
++      return tdesc;
++}
++
++int usecount(void)
++{
++      int res;
++      STANDARD_USECOUNT(res);
++      return res;
++}
++
++char *key()
++{
++      return ASTERISK_GPL_KEY;
++}
+diff -urN asterisk-1.2.4.orig/apps/app_capiNoES.c asterisk-1.2.4/apps/app_capiNoES.c
+--- asterisk-1.2.4.orig/apps/app_capiNoES.c    1970-01-01 01:00:00.000000000 +0100
++++ asterisk-1.2.4/apps/app_capiNoES.c 2006-01-31 09:41:43.000000000 +0100
+@@ -0,0 +1,96 @@
++/*
++ * (CAPI*)
++ *
++ * An implementation of Common ISDN API 2.0 for Asterisk
++ *
++ * Disable echo suppression (useful for fax and voicemail!)
++ *
++ * Copyright (C) 2004,2005 Junghanns.NET GmbH
++ *
++ * Klaus-Peter Junghanns <kapejod@ns1.jnetdns.de>
++ *
++ * This program is free software and may be modified and 
++ * distributed under the terms of the GNU Public License.
++ */
++
++#include <stdlib.h>
++#include <unistd.h>
++#include <string.h>
++#include <stdio.h>
++#include <linux/capi.h>
++#include <capi20.h>
++
++#include <asterisk/file.h>
++#include <asterisk/logger.h>
++#include <asterisk/channel.h>
++#include <asterisk/pbx.h>
++#include <asterisk/module.h>
++#include <asterisk/chan_capi_app.h>
++
++
++
++#ifdef CAPI_ES
++static char *tdesc = "(CAPI*) No Echo Suppression.";
++static char *app = "capiNoES";
++static char *synopsis = "Disable Echo Suppression";
++#else
++static char *tdesc = "(CAPI*) No Echo Suppression at all!";
++static char *app = "capiNoES";
++static char *synopsis = "Bogus Application";
++#endif
++STANDARD_LOCAL_USER;
++
++LOCAL_USER_DECL;
++
++static int capiNoES_exec(struct ast_channel *chan, void *data)
++{
++    int res=0;
++    struct localuser *u;
++    LOCAL_USER_ADD(u);
++
++#ifdef CAPI_ES
++    if (strcasecmp("CAPI",chan->type) == 0) {
++#ifdef CVS_HEAD
++      struct ast_capi_pvt *i = chan->tech_pvt;
++#else
++      struct ast_capi_pvt *i = chan->pvt->pvt;
++#endif
++      if (i->doES == 1) {
++          i->doES = 0;
++      }
++    } else {
++      ast_log(LOG_WARNING, "capiNoES only works on CAPI channels, check your extensions.conf!\n");
++    }
++#endif
++
++    LOCAL_USER_REMOVE(u);
++    return res;
++}
++
++int unload_module(void)
++{
++      STANDARD_HANGUP_LOCALUSERS;
++      return ast_unregister_application(app);
++}
++
++int load_module(void)
++{
++      return ast_register_application(app, capiNoES_exec,synopsis,tdesc);
++}
++
++char *description(void)
++{
++      return tdesc;
++}
++
++int usecount(void)
++{
++      int res;
++      STANDARD_USECOUNT(res);
++      return res;
++}
++
++char *key()
++{
++      return ASTERISK_GPL_KEY;
++}
+diff -urN asterisk-1.2.4.orig/apps/app_chanisavail.c asterisk-1.2.4/apps/app_chanisavail.c
+--- asterisk-1.2.4.orig/apps/app_chanisavail.c 2005-11-29 19:24:39.000000000 +0100
++++ asterisk-1.2.4/apps/app_chanisavail.c      2006-01-31 09:41:43.000000000 +0100
+@@ -118,7 +118,7 @@
+                               snprintf(trychan, sizeof(trychan), "%s/%s",cur,number);
+                               status = inuse = ast_device_state(trychan);
+                       }
+-                      if ((inuse <= 1) && (tempchan = ast_request(tech, chan->nativeformats, number, &status))) {
++                      if ((inuse <= 1) && (tempchan = ast_request(tech, chan->nativeformats, number, &status, NULL))) {
+                                       pbx_builtin_setvar_helper(chan, "AVAILCHAN", tempchan->name);
+                                       /* Store the originally used channel too */
+                                       snprintf(tmp, sizeof(tmp), "%s/%s", tech, number);
+diff -urN asterisk-1.2.4.orig/apps/app_devstate.c asterisk-1.2.4/apps/app_devstate.c
+--- asterisk-1.2.4.orig/apps/app_devstate.c    1970-01-01 01:00:00.000000000 +0100
++++ asterisk-1.2.4/apps/app_devstate.c 2006-01-31 09:41:43.000000000 +0100
+@@ -0,0 +1,219 @@
++/*
++ * Devstate application
++ * 
++ * Since we like the snom leds so much, a little app to
++ * light the lights on the snom on demand ....
++ *
++ * Copyright (C) 2005, Druid Software
++ *
++ * This program is free software, distributed under the terms of
++ * the GNU General Public License
++ */
++
++#include <stdlib.h>
++#include <unistd.h>
++#include <string.h>
++#include <stdio.h>
++#include <asterisk/lock.h>
++#include <asterisk/file.h>
++#include <asterisk/logger.h>
++#include <asterisk/channel.h>
++#include <asterisk/pbx.h>
++#include <asterisk/module.h>
++#include <asterisk/astdb.h>
++#include <asterisk/utils.h>
++#include <asterisk/cli.h>
++#include <asterisk/manager.h>
++#include <asterisk/devicestate.h>
++
++
++static char type[] = "DS";
++static char tdesc[] = "Application for sending device state messages";
++
++static char app[] = "Devstate";
++
++static char synopsis[] = "Generate a device state change event given the input parameters";
++
++static char descrip[] = " Devstate(device|state):  Generate a device state change event given the input parameters. Returns 0. State values match the asterisk device states. They are 0 = unknown, 1 = not inuse, 2 = inuse, 3 = busy, 4 = invalid, 5 = unavailable, 6 = ringing\n";
++
++static char devstate_cli_usage[] = 
++"Usage: devstate device state\n" 
++"       Generate a device state change event given the input parameters.\n Mainly used for lighting the LEDs on the snoms.\n";
++
++static int devstate_cli(int fd, int argc, char *argv[]);
++static struct ast_cli_entry  cli_dev_state =
++        { { "devstate", NULL }, devstate_cli, "Set the device state on one of the \"pseudo devices\".", devstate_cli_usage };
++
++STANDARD_LOCAL_USER;
++
++LOCAL_USER_DECL;
++
++
++static int devstate_cli(int fd, int argc, char *argv[])
++{
++    char devName[128];
++    if ((argc != 3) && (argc != 4))
++        return RESULT_SHOWUSAGE;
++
++    if (ast_db_put("DEVSTATES", argv[1], argv[2]))
++    {
++        ast_log(LOG_DEBUG, "ast_db_put failed\n");
++    }
++    snprintf(devName, sizeof(devName), "DS/%s", argv[1]);
++    if (argc == 4) {
++        ast_log(LOG_NOTICE, "devname %s cid %s\n", devName, argv[3]);
++      ast_device_state_changed_literal(devName, argv[3], NULL);
++    } else {
++      ast_device_state_changed_literal(devName, NULL, NULL);
++    }
++    return RESULT_SUCCESS;
++}
++
++static int devstate_exec(struct ast_channel *chan, void *data)
++{
++    struct localuser *u;
++    char *device, *state, *info;
++    char devName[128];
++    if (!(info = ast_strdupa(data))) {
++            ast_log(LOG_WARNING, "Unable to dupe data :(\n");
++            return -1;
++    }
++    LOCAL_USER_ADD(u);
++    
++    device = info;
++    state = strchr(info, '|');
++    if (state) {
++        *state = '\0';
++        state++;
++    }
++    else
++    {
++        ast_log(LOG_DEBUG, "No state argument supplied\n");
++        return -1;
++    }
++
++    if (ast_db_put("DEVSTATES", device, state))
++    {
++        ast_log(LOG_DEBUG, "ast_db_put failed\n");
++    }
++
++    snprintf(devName, sizeof(devName), "DS/%s", device);
++    ast_device_state_changed_literal(devName, NULL, NULL);
++
++    LOCAL_USER_REMOVE(u);
++    return 0;
++}
++
++
++static int ds_devicestate(void *data)
++{
++    char *dest = data;
++    char stateStr[16];
++    if (ast_db_get("DEVSTATES", dest, stateStr, sizeof(stateStr)))
++    {
++        ast_log(LOG_DEBUG, "ds_devicestate couldnt get state in astdb\n");
++        return 0;
++    }
++    else
++    {
++        ast_log(LOG_DEBUG, "ds_devicestate dev=%s returning state %d\n",
++               dest, atoi(stateStr));
++        return (atoi(stateStr));
++    }
++}
++
++static struct ast_channel_tech devstate_tech = {
++      .type = type,
++      .description = tdesc,
++      .capabilities = ((AST_FORMAT_MAX_AUDIO << 1) - 1),
++      .devicestate = ds_devicestate,
++      .requester = NULL,
++      .send_digit = NULL,
++      .send_text = NULL,
++      .call = NULL,
++      .hangup = NULL,
++      .answer = NULL,
++      .read = NULL,
++      .write = NULL,
++      .bridge = NULL,
++      .exception = NULL,
++      .indicate = NULL,
++      .fixup = NULL,
++      .setoption = NULL,
++};
++
++static char mandescr_devstate[] = 
++"Description: Put a value into astdb\n"
++"Variables: \n"
++"     Family: ...\n"
++"     Key: ...\n"
++"     Value: ...\n";
++
++static int action_devstate(struct mansession *s, struct message *m)
++{
++        char *devstate = astman_get_header(m, "Devstate");
++        char *value = astman_get_header(m, "Value");
++      char *id = astman_get_header(m,"ActionID");
++      char devName[128];
++
++      if (!strlen(devstate)) {
++              astman_send_error(s, m, "No Devstate specified");
++              return 0;
++      }
++      if (!strlen(value)) {
++              astman_send_error(s, m, "No Value specified");
++              return 0;
++      }
++
++        if (!ast_db_put("DEVSTATES", devstate, value)) {
++          snprintf(devName, sizeof(devName), "DS/%s", devstate);
++          ast_device_state_changed(devName);
++          ast_cli(s->fd, "Response: Success\r\n");
++      } else {
++          ast_log(LOG_DEBUG, "ast_db_put failed\n");
++          ast_cli(s->fd, "Response: Failed\r\n");
++      }
++      if (id && !ast_strlen_zero(id))
++              ast_cli(s->fd, "ActionID: %s\r\n",id);
++      ast_cli(s->fd, "\r\n");
++      return 0;
++}
++
++int load_module(void)
++{
++    if (ast_channel_register(&devstate_tech)) {
++        ast_log(LOG_DEBUG, "Unable to register channel class %s\n", type);
++        return -1;
++    }
++    ast_cli_register(&cli_dev_state);  
++    ast_manager_register2( "Devstate", EVENT_FLAG_CALL, action_devstate, "Change a device state", mandescr_devstate );
++    return ast_register_application(app, devstate_exec, synopsis, descrip);
++}
++
++int unload_module(void)
++{
++    int res = 0;
++    STANDARD_HANGUP_LOCALUSERS;
++    ast_manager_unregister( "Devstate");
++    ast_cli_unregister(&cli_dev_state);
++    res = ast_unregister_application(app);
++    ast_channel_unregister(&devstate_tech);    
++    return res;
++}
++
++char *description(void)
++{
++    return tdesc;
++}
++
++int usecount(void)
++{
++    int res;
++    STANDARD_USECOUNT(res);
++    return res;
++}
++
++char *key()
++{
++    return ASTERISK_GPL_KEY;
++}
+diff -urN asterisk-1.2.4.orig/apps/app_dial.c asterisk-1.2.4/apps/app_dial.c
+--- asterisk-1.2.4.orig/apps/app_dial.c        2006-01-25 02:50:52.000000000 +0100
++++ asterisk-1.2.4/apps/app_dial.c     2006-01-31 09:41:43.000000000 +0100
+@@ -11,6 +11,10 @@
+  * the project provides a web site, mailing lists and IRC
+  * channels for your use.
+  *
++ * Copyright (C) 2004, Junghanns.NET GmbH
++ *
++ * Klaus-Peter Junghanns <kpj@junghanns.net>
++ *
+  * This program is free software, distributed under the terms of
+  * the GNU General Public License Version 2. See the LICENSE file
+  * at the top of the source tree.
+@@ -113,7 +117,8 @@
+ "           context may be specified. Otherwise, the current extension is used.\n"
+ "    h    - Allow the called party to hang up by sending the '*' DTMF digit.\n"
+ "    H    - Allow the calling party to hang up by hitting the '*' DTMF digit.\n"
+-"    j    - Jump to priority n+101 if all of the requested channels were busy.\n"
++"    j    - Jump to priority n+101 if the called party was busy.\n"
++"           Jump to priority n+201 if all of the requested channels were busy.\n"
+ "    L(x[:y][:z]) - Limit the call to 'x' ms. Play a warning when 'y' ms are\n"
+ "           left. Repeat the warning every 'z' ms. The following special\n"
+ "           variables can be used with this option:\n"
+@@ -158,8 +163,11 @@
+ "           family/key is not specified.\n"
+ "    r    - Indicate ringing to the calling party. Pass no audio to the calling\n"
+ "           party until the called channel has answered.\n"
++"    R          - indicate ringing to the calling party when the called party indicates\n"
++"            ringing, pass no audio until answered.\n"
+ "    S(x) - Hang up the call after 'x' seconds *after* the called party has\n"
+-"           answered the call.\n"     
++"           answered the call.\n"
++"    c    - callback initiation, ring once and hangup.\n"
+ "    t    - Allow the called party to transfer the calling party by sending the\n"
+ "           DTMF sequence defined in features.conf.\n"
+ "    T    - Allow the calling party to transfer the called party by sending the\n"
+@@ -210,6 +218,8 @@
+       OPT_CALLEE_MONITOR = (1 << 21),
+       OPT_CALLER_MONITOR = (1 << 22),
+       OPT_GOTO = (1 << 23),
++      OPT_NOINBAND = (1 << 24),
++      OPT_CALLBACK_INIT = (1 << 25),
+ } dial_exec_option_flags;
+ #define DIAL_STILLGOING                       (1 << 30)
+@@ -248,6 +258,8 @@
+       AST_APP_OPTION('p', OPT_SCREENING),
+       AST_APP_OPTION_ARG('P', OPT_PRIVACY, OPT_ARG_PRIVACY),
+       AST_APP_OPTION('r', OPT_RINGBACK),
++      AST_APP_OPTION('R', OPT_NOINBAND),
++      AST_APP_OPTION('c', OPT_CALLBACK_INIT),
+       AST_APP_OPTION_ARG('S', OPT_DURATION_STOP, OPT_ARG_DURATION_STOP),
+       AST_APP_OPTION('t', OPT_CALLEE_TRANSFER),
+       AST_APP_OPTION('T', OPT_CALLER_TRANSFER),
+@@ -383,7 +395,7 @@
+       char *context = NULL;
+       char cidname[AST_MAX_EXTENSION];
+-      single = (outgoing && !outgoing->next && !ast_test_flag(outgoing, OPT_MUSICBACK | OPT_RINGBACK));
++      single = (outgoing && !outgoing->next && !ast_test_flag(outgoing, OPT_MUSICBACK | OPT_RINGBACK | OPT_NOINBAND));
+       
+       if (single) {
+               /* Turn off hold music, etc */
+@@ -462,7 +474,7 @@
+                                               if (option_verbose > 2)
+                                                       ast_verbose(VERBOSE_PREFIX_3 "Now forwarding %s to '%s/%s' (thanks to %s)\n", in->name, tech, stuff, o->chan->name);
+                                               /* Setup parameters */
+-                                              o->chan = ast_request(tech, in->nativeformats, stuff, &cause);
++                                              o->chan = ast_request(tech, in->nativeformats, stuff, &cause, NULL);
+                                               if (!o->chan)
+                                                       ast_log(LOG_NOTICE, "Unable to create local channel for call forward to '%s/%s' (cause = %d)\n", tech, stuff, cause);
+                                       } else {
+@@ -916,17 +928,24 @@
+               }
+               
+               if( privdb_val == AST_PRIVACY_DENY ) {
++                      ast_copy_string(status, "NOANSWER", sizeof(status));
+                       ast_verbose( VERBOSE_PREFIX_3  "Privacy DB reports PRIVACY_DENY for this callerid. Dial reports unavailable\n");
+                       res=0;
+                       goto out;
+               }
+               else if( privdb_val == AST_PRIVACY_KILL ) {
+-                      ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 201);
++                      ast_copy_string(status, "DONTCALL", sizeof(status));
++                      if (option_priority_jumping || ast_test_flag(&opts, OPT_PRIORITY_JUMP)) {
++                              ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 201);
++                      }
+                       res = 0;
+                       goto out; /* Is this right? */
+               }
+               else if( privdb_val == AST_PRIVACY_TORTURE ) {
+-                      ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 301);
++                      ast_copy_string(status, "TORTURE", sizeof(status));
++                      if (option_priority_jumping || ast_test_flag(&opts, OPT_PRIORITY_JUMP)) {
++                              ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 301);
++                      }
+                       res = 0;
+                       goto out; /* is this right??? */
+@@ -1005,7 +1024,7 @@
+                               ast_log(LOG_DEBUG, "Dialing by extension %s\n", numsubst);
+               }
+               /* Request the peer */
+-              tmp->chan = ast_request(tech, chan->nativeformats, numsubst, &cause);
++              tmp->chan = ast_request(tech, chan->nativeformats, numsubst, &cause, NULL);
+               if (!tmp->chan) {
+                       /* If we can't, just go on to the next call */
+                       ast_log(LOG_NOTICE, "Unable to create channel of type '%s' (cause %d - %s)\n", tech, cause, ast_cause2str(cause));
+@@ -1036,7 +1055,7 @@
+                                       ast_verbose(VERBOSE_PREFIX_3 "Now forwarding %s to '%s/%s' (thanks to %s)\n", chan->name, tech, stuff, tmp->chan->name);
+                               ast_hangup(tmp->chan);
+                               /* Setup parameters */
+-                              tmp->chan = ast_request(tech, chan->nativeformats, stuff, &cause);
++                              tmp->chan = ast_request(tech, chan->nativeformats, stuff, &cause, NULL);
+                               if (!tmp->chan)
+                                       ast_log(LOG_NOTICE, "Unable to create local channel for call forward to '%s/%s' (cause = %d)\n", tech, stuff, cause);
+                       } else {
+@@ -1155,8 +1174,11 @@
+                       ast_indicate(chan, AST_CONTROL_RINGING);
+                       sentringing++;
+               }
+-      } else
++      } else {
+               strcpy(status, "CHANUNAVAIL");
++              /* See if there is a special message */
++              ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 201);
++      }
+       time(&start_time);
+       peer = wait_for_answer(chan, outgoing, &to, peerflags, &sentringing, status, sizeof(status), numbusy, numnochan, numcongestion, ast_test_flag(&opts, OPT_PRIORITY_JUMP), &result);
+@@ -1285,6 +1307,8 @@
+                                                                    opt_args[OPT_ARG_PRIVACY], privcid);
+                                               ast_privacy_set(opt_args[OPT_ARG_PRIVACY], privcid, AST_PRIVACY_DENY);
+                                       }
++                                      ast_copy_string(status, "NOANSWER", sizeof(status));
++
+                                       if (ast_test_flag(&opts, OPT_MUSICBACK)) {
+                                               ast_moh_stop(chan);
+                                       } else if (ast_test_flag(&opts, OPT_RINGBACK)) {
+diff -urN asterisk-1.2.4.orig/apps/app_directed_pickup.c asterisk-1.2.4/apps/app_directed_pickup.c
+--- asterisk-1.2.4.orig/apps/app_directed_pickup.c     2005-12-20 18:34:00.000000000 +0100
++++ asterisk-1.2.4/apps/app_directed_pickup.c  2006-01-31 09:41:43.000000000 +0100
+@@ -41,7 +41,7 @@
+ #include "asterisk/app.h"
+ static const char *tdesc = "Directed Call Pickup Application";
+-static const char *app = "Pickup";
++static const char *app = "DPickup";
+ static const char *synopsis = "Directed Call Pickup";
+ static const char *descrip =
+ "  Pickup(extension[@context]): This application can pickup any ringing channel\n"
+diff -urN asterisk-1.2.4.orig/apps/app_meetme.c asterisk-1.2.4/apps/app_meetme.c
+--- asterisk-1.2.4.orig/apps/app_meetme.c      2006-01-18 22:02:06.000000000 +0100
++++ asterisk-1.2.4/apps/app_meetme.c   2006-01-31 09:41:43.000000000 +0100
+@@ -454,7 +454,7 @@
+                       ast_copy_string(cnf->pin, pin, sizeof(cnf->pin));
+                       ast_copy_string(cnf->pinadmin, pinadmin, sizeof(cnf->pinadmin));
+                       cnf->markedusers = 0;
+-                      cnf->chan = ast_request("zap", AST_FORMAT_ULAW, "pseudo", NULL);
++                      cnf->chan = ast_request("zap", AST_FORMAT_ULAW, "pseudo", NULL, NULL);
+                       if (cnf->chan) {
+                               cnf->fd = cnf->chan->fds[0];    /* for use by conf_play() */
+                       } else {
+@@ -822,8 +822,9 @@
+       char exitcontext[AST_MAX_CONTEXT] = "";
+       char recordingtmp[AST_MAX_EXTENSION] = "";
+       int dtmf;
++      int dyna_buff = CONF_SIZE;
+       ZT_BUFFERINFO bi;
+-      char __buf[CONF_SIZE + AST_FRIENDLY_OFFSET];
++      char __buf[ZT_MAX_BUF_SPACE / ZT_DEFAULT_NUM_BUFS + AST_FRIENDLY_OFFSET];
+       char *buf = __buf + AST_FRIENDLY_OFFSET;
+       
+       if (!user) {
+@@ -986,7 +987,7 @@
+               }
+               /* Setup buffering information */
+               memset(&bi, 0, sizeof(bi));
+-              bi.bufsize = CONF_SIZE/2;
++              bi.bufsize = dyna_buff / 2;
+               bi.txbufpolicy = ZT_POLICY_IMMEDIATE;
+               bi.rxbufpolicy = ZT_POLICY_IMMEDIATE;
+               bi.numbufs = audio_buffers;
+@@ -1271,6 +1272,14 @@
+                               f = ast_read(c);
+                               if (!f)
+                                       break;
++                              if (f->datalen && f->datalen != dyna_buff) {
++                                      ast_log(LOG_NOTICE, "Audio bytes: %d  Buffer size: %d\n", f->datalen, dyna_buff);
++                                      if (f->datalen < ZT_MAX_BUF_SPACE/audio_buffers) { /* skip too large frame to avoid overflow */
++                                              dyna_buff = f->datalen;
++                                              close(fd);
++                                              goto zapretry;
++                                      }
++                              }
+                               if ((f->frametype == AST_FRAME_VOICE) && (f->subclass == AST_FORMAT_SLINEAR)) {
+                                       if (user->talk.actual)
+                                               ast_frame_adjust_volume(f, user->talk.actual);
+@@ -1500,7 +1509,7 @@
+                               }
+                               ast_frfree(f);
+                       } else if (outfd > -1) {
+-                              res = read(outfd, buf, CONF_SIZE);
++                              res = read(outfd, buf, dyna_buff);
+                               if (res > 0) {
+                                       memset(&fr, 0, sizeof(fr));
+                                       fr.frametype = AST_FRAME_VOICE;
+diff -urN asterisk-1.2.4.orig/apps/app_milliwatt.c asterisk-1.2.4/apps/app_milliwatt.c
+--- asterisk-1.2.4.orig/apps/app_milliwatt.c   2006-01-19 05:17:45.000000000 +0100
++++ asterisk-1.2.4/apps/app_milliwatt.c        2006-01-31 09:41:43.000000000 +0100
+@@ -74,20 +74,28 @@
+ {
+       struct ast_frame wf;
+       unsigned char buf[AST_FRIENDLY_OFFSET + 640];
++      const int maxsamples = (sizeof (buf) - AST_FRIENDLY_OFFSET) / sizeof (buf[0]);
+       int i,*indexp = (int *) data;
+-      if (len + AST_FRIENDLY_OFFSET > sizeof(buf))
+-      {
+-              ast_log(LOG_WARNING,"Only doing %d bytes (%d bytes requested)\n",(int)(sizeof(buf) - AST_FRIENDLY_OFFSET),len);
+-              len = sizeof(buf) - AST_FRIENDLY_OFFSET;
+-      }
++      /* Instead of len, use samples, because channel.c generator_force 
++       * generate(chan, tmp, 0, 160) ignores len. In any case, len is  
++       * a multiple of samples, given by number of samples times bytes per
++       * sample. In the case of ulaw, len = samples. for signed linear 
++       * len = 2 * samples                                                 */
++ 
++      if (samples > maxsamples)
++      {
++              ast_log(LOG_WARNING, "Only doing %d samples (%d requested)\n", maxsamples, samples);
++              samples = maxsamples;
++      }
++      len = samples * sizeof (buf[0]);
+       wf.frametype = AST_FRAME_VOICE;
+       wf.subclass = AST_FORMAT_ULAW;
+       wf.offset = AST_FRIENDLY_OFFSET;
+       wf.mallocd = 0;
+       wf.data = buf + AST_FRIENDLY_OFFSET;
+       wf.datalen = len;
+-      wf.samples = wf.datalen;
++      wf.samples = samples;
+       wf.src = "app_milliwatt";
+       wf.delivery.tv_sec = 0;
+       wf.delivery.tv_usec = 0;
+diff -urN asterisk-1.2.4.orig/apps/app_page.c asterisk-1.2.4/apps/app_page.c
+--- asterisk-1.2.4.orig/apps/app_page.c        2005-12-02 01:51:15.000000000 +0100
++++ asterisk-1.2.4/apps/app_page.c     2006-01-31 09:41:43.000000000 +0100
+@@ -85,7 +85,7 @@
+ {
+       struct calloutdata *cd = data;
+       ast_pbx_outgoing_app(cd->tech, AST_FORMAT_SLINEAR, cd->resource, 30000,
+-              "MeetMe", cd->meetmeopts, NULL, 0, cd->cidnum, cd->cidname, cd->variables, NULL);
++              "MeetMe", cd->meetmeopts, NULL, 0, 0, cd->cidnum, cd->cidname, cd->variables, NULL, NULL);
+       free(cd);
+       return NULL;
+ }
+diff -urN asterisk-1.2.4.orig/apps/app_parkandannounce.c asterisk-1.2.4/apps/app_parkandannounce.c
+--- asterisk-1.2.4.orig/apps/app_parkandannounce.c     2005-11-29 19:24:39.000000000 +0100
++++ asterisk-1.2.4/apps/app_parkandannounce.c  2006-01-31 09:41:43.000000000 +0100
+@@ -183,7 +183,7 @@
+       memset(&oh, 0, sizeof(oh));
+       oh.parent_channel = chan;
+-      dchan = __ast_request_and_dial(dialtech, AST_FORMAT_SLINEAR, dialstr,30000, &outstate, chan->cid.cid_num, chan->cid.cid_name, &oh);
++      dchan = __ast_request_and_dial(dialtech, AST_FORMAT_SLINEAR, dialstr,30000, &outstate, 0, chan->cid.cid_num, chan->cid.cid_name, &oh, NULL);
+       if(dchan) {
+               if(dchan->_state == AST_STATE_UP) {
+diff -urN asterisk-1.2.4.orig/apps/app_pickup.c asterisk-1.2.4/apps/app_pickup.c
+--- asterisk-1.2.4.orig/apps/app_pickup.c      1970-01-01 01:00:00.000000000 +0100
++++ asterisk-1.2.4/apps/app_pickup.c   2006-01-31 09:41:43.000000000 +0100
+@@ -0,0 +1,319 @@
++/*
++ * Asterisk -- A telephony toolkit for Linux.
++ *
++ * Pickup, channel independent call pickup
++ * 
++ * Copyright (C) 2004, Junghanns.NET GmbH
++ *
++ * Klaus-Peter Junghanns <kpj@junghanns.net>
++ *
++ * Copyright (C) 2004, Florian Overkamp <florian@obsimref.com>
++ *
++ * This program is free software, distributed under the terms of
++ * the GNU General Public License
++ */
++
++#include <stdlib.h>
++#include <unistd.h>
++#include <string.h>
++#include <stdio.h>
++#include <signal.h>
++#include <pthread.h>
++#include <asterisk/lock.h>
++#include <asterisk/file.h>
++#include <asterisk/logger.h>
++#include <asterisk/channel.h>
++#include <asterisk/pbx.h>
++#include <asterisk/module.h>
++#include <asterisk/features.h>
++#include <asterisk/options.h>
++
++
++static char *tdesc = "PickUp/PickDown/Steal/PickupChan/StealChan";
++
++static char *app = "PickUp";
++
++static char *synopsis = "Channel independent call pickup.";
++
++static char *descrip = 
++"  PickDown([group]):  Tries to pickup the first ringing channel with callgroup == group.\n"
++"                    If called without the group argument, the pickupgroup of the channel will be used.\n";
++
++static char *app2 = "Steal";
++
++static char *synopsis2 = "Channel independent call stealing. Just like pickup but for answered channels.";
++
++static char *descrip2 = 
++"  Steal([group]):  Tries to steal the first bridged channel with callgroup == group.\n"
++"                    If called without the group argument, the pickupgroup of the channel will be used.\n";
++
++static char *app3 = "PickDown";
++
++static char *synopsis3 = "Channel independent call pickdown.";
++
++static char *descrip3 = 
++"  PickDown([group]):  Tries to hangup the first ringing channel with callgroup == group.\n"
++"                    If called without the group argument, the pickupgroup of the channel will be used.\n";
++
++static char *app4 = "PickupChan";
++
++static char *synopsis4 = "Channel independent call pickup.";
++
++static char *descrip4 = 
++"  PickupChan(Technology/resource[&Technology2/resource2...]):  Tries to pickup the first ringing channel in the parameter list.\n";
++
++static char *app5 = "StealChan";
++
++static char *synopsis5 = "Channel independent call stealing. Just like pickup but for answered channels.";
++
++static char *descrip5 = 
++"  StealChan(Technology/resource[&Technology2/resource2...]):  Tries to steal the first ringing channel in the parameter list.\n";
++
++STANDARD_LOCAL_USER;
++
++LOCAL_USER_DECL;
++
++static int my_pickup_call(struct ast_channel *chan, unsigned int pickupgroup, int chanstate, int bridge) {
++      struct ast_channel *cur;
++      int res = -1;
++      cur = ast_channel_walk_locked(NULL);
++      while(cur) {
++              if ((cur != chan) &&
++                      (pickupgroup & cur->callgroup) &&
++                       (cur->_state == chanstate)) {
++                              break;
++              }
++              ast_mutex_unlock(&cur->lock);
++              cur = ast_channel_walk_locked(cur);
++      }
++      if (cur) {
++              if(option_verbose > 2) {
++                  if (chanstate == AST_STATE_RINGING) {
++                      if (bridge == 1) {
++                          ast_verbose(VERBOSE_PREFIX_3 "Channel %s picked up ringing channel %s\n",chan->name,cur->name);
++                      } else {
++                          ast_verbose(VERBOSE_PREFIX_3 "Channel %s hung up ringing channel %s\n",chan->name,cur->name);
++                      }
++                  } else {
++                      ast_verbose(VERBOSE_PREFIX_3 "Channel %s stole channel %s\n",chan->name,cur->name);
++                  }
++              }
++              if (bridge == 1) {
++                  if (chan->_state != AST_STATE_UP) {
++                      ast_answer(chan);
++                  }
++                  if (ast_channel_masquerade(cur, chan)) {
++                      ast_log(LOG_ERROR, "unable to masquerade\n");
++                  }
++                  ast_mutex_unlock(&cur->lock);
++                  ast_mutex_unlock(&chan->lock);
++              } else {
++                  cur->_softhangup = AST_SOFTHANGUP_DEV;
++                  ast_mutex_unlock(&cur->lock);
++              }
++      } else  {
++              if(option_verbose > 2) {
++                  ast_verbose(VERBOSE_PREFIX_3 "No channel found %d.\n",pickupgroup);
++              }
++      } 
++      return res;
++}
++
++static int my_pickup_channel(struct ast_channel *chan, void *data, int chanstate, int bridge) {
++       struct ast_channel *cur;
++       char channels[256];
++       char evalchan[256];
++       char *endptr;
++       int res = -1;
++       cur = ast_channel_walk_locked(NULL);
++       strncpy(channels, (char *)data, sizeof(channels) - 1);
++       while(cur) {
++               if ((cur != chan) &&
++                        (cur->_state == chanstate)) {
++                               /* This call is a candidate (correct ringstate and not ourselves), now check if the channel is in our list */
++                               strncpy(evalchan, (char *)cur->name, sizeof(evalchan) - 1);                             
++                               /* strip the subchannel tag */
++                               endptr = strrchr(evalchan, '-');
++                               if(endptr) {
++                                       *endptr = '\0';
++                               }
++                               endptr = strrchr(evalchan, '/');
++                               if(endptr) {
++                                       *endptr = '\0';
++                               }
++                               /* check for each of the members if they match (probably a stristr will do ?) */
++                               /* if we match the code, break */
++                               if(strstr(channels, evalchan) != NULL) {
++                                       ast_verbose(VERBOSE_PREFIX_1 "Nice channel, I'll take it: %s\n",evalchan);
++                                       break;
++                               }
++               }
++               ast_mutex_unlock(&cur->lock);
++               cur = ast_channel_walk_locked(cur);
++       }
++       if (cur) {
++               if(option_verbose > 2) {
++                   if (chanstate == AST_STATE_RINGING) {
++                       if (bridge == 1) {
++                           ast_verbose(VERBOSE_PREFIX_3 "Channel %s picked up ringing channel %s\n",chan->name,cur->name);
++                       } else {
++                           ast_verbose(VERBOSE_PREFIX_3 "Channel %s hung up ringing channel %s\n",chan->name,cur->name);
++                       }
++                   } else {
++                       ast_verbose(VERBOSE_PREFIX_3 "Channel %s stole channel %s\n",chan->name,cur->name);
++                   }
++               }
++               if (bridge == 1) {
++                 if (chan->_state != AST_STATE_UP) {
++                     ast_answer(chan);
++                 }
++                   if (ast_channel_masquerade(cur, chan)) {
++                       ast_log(LOG_ERROR, "unable to masquerade\n");
++                   }
++                   ast_mutex_unlock(&cur->lock);
++                   ast_mutex_unlock(&chan->lock);
++               } else {
++                   cur->_softhangup = AST_SOFTHANGUP_DEV;
++                   ast_mutex_unlock(&cur->lock);
++               }
++       } else  {
++               if(option_verbose > 2) {
++                   ast_verbose(VERBOSE_PREFIX_3 "No channel found %s.\n",channels);
++               }
++       } 
++       return res;
++}
++
++
++static int pickup_exec(struct ast_channel *chan, void *data)
++{
++      int res=0;
++      unsigned int pickupgroup=0;
++      struct localuser *u;
++      if (!data || !strlen(data)) {
++          pickupgroup = chan->pickupgroup;
++      } else {
++          pickupgroup = ast_get_group(data);
++      }
++      LOCAL_USER_ADD(u);
++      if (!res) {
++              res = my_pickup_call(chan, pickupgroup, AST_STATE_RINGING, 1);
++      }
++      if (res > 0)
++              res = 0;
++      LOCAL_USER_REMOVE(u);
++      return res;
++}
++
++static int steal_exec(struct ast_channel *chan, void *data)
++{
++      int res=0;
++      unsigned int pickupgroup=0;
++      struct localuser *u;
++      if (!data || !strlen(data)) {
++          pickupgroup = chan->pickupgroup;
++      } else {
++          pickupgroup = ast_get_group(data);
++      }
++      LOCAL_USER_ADD(u);
++      if (!res) {
++              res = my_pickup_call(chan, pickupgroup, AST_STATE_UP, 1);
++      }
++      if (res > 0)
++              res = 0;
++      LOCAL_USER_REMOVE(u);
++      return res;
++}
++
++static int pickdown_exec(struct ast_channel *chan, void *data)
++{
++      int res=0;
++      unsigned int pickupgroup=0;
++      struct localuser *u;
++      if (!data || !strlen(data)) {
++          pickupgroup = chan->pickupgroup;
++      } else {
++          pickupgroup = ast_get_group(data);
++      }
++      LOCAL_USER_ADD(u);
++      if (!res) {
++              res = my_pickup_call(chan, pickupgroup, AST_STATE_RINGING, 0);
++      }
++      if (res > 0)
++              res = 0;
++      LOCAL_USER_REMOVE(u);
++      return res;
++}
++
++static int pickupchan_exec(struct ast_channel *chan, void *data) {
++       int res=0;
++       struct localuser *u;
++        if (!data) {
++                ast_log(LOG_WARNING, "PickupChan requires an argument (technology1/number1&technology2/number2...)\n");
++                return -1;
++        }
++       LOCAL_USER_ADD(u);
++       if (!res) {
++               res = my_pickup_channel(chan, data, AST_STATE_RINGING, 1);
++       }
++       if (res > 0)
++               res = 0;
++       LOCAL_USER_REMOVE(u);
++       return res;
++}
++
++static int stealchan_exec(struct ast_channel *chan, void *data)
++{
++      int res=0;
++      struct localuser *u;
++        if (!data) {
++                ast_log(LOG_WARNING, "StealChan requires an argument (technology1/number1&technology2/number2...)\n");
++                return -1;
++        }
++
++      LOCAL_USER_ADD(u);
++      if (!res) {
++              res = my_pickup_channel(chan, data, AST_STATE_UP, 1);
++      }
++      if (res > 0)
++              res = 0;
++      LOCAL_USER_REMOVE(u);
++      return res;
++}
++
++
++int unload_module(void)
++{
++      STANDARD_HANGUP_LOCALUSERS;
++      ast_unregister_application(app5);
++      ast_unregister_application(app4);
++      ast_unregister_application(app3);
++      ast_unregister_application(app2);
++      return ast_unregister_application(app);
++}
++
++int load_module(void)
++{
++      ast_register_application(app5, stealchan_exec, synopsis5, descrip5);
++      ast_register_application(app4, pickupchan_exec, synopsis4, descrip4);
++      ast_register_application(app3, pickdown_exec, synopsis3, descrip3);
++      ast_register_application(app2, steal_exec, synopsis2, descrip2);
++      return ast_register_application(app, pickup_exec, synopsis, descrip);
++}
++
++char *description(void)
++{
++      return tdesc;
++}
++
++int usecount(void)
++{
++      int res;
++      STANDARD_USECOUNT(res);
++      return res;
++}
++
++char *key()
++{
++      return ASTERISK_GPL_KEY;
++}
+diff -urN asterisk-1.2.4.orig/apps/app_queue.c asterisk-1.2.4/apps/app_queue.c
+--- asterisk-1.2.4.orig/apps/app_queue.c       2006-01-22 20:03:53.000000000 +0100
++++ asterisk-1.2.4/apps/app_queue.c    2006-01-31 09:41:43.000000000 +0100
+@@ -501,7 +501,7 @@
+       return NULL;
+ }
+-static int statechange_queue(const char *dev, int state, void *ign)
++static int statechange_queue(const char *dev, int state, void *ign, char *cid_num, char *cid_name)
+ {
+       /* Avoid potential for deadlocks by spawning a new thread to handle
+          the event */
+@@ -1386,7 +1386,7 @@
+               location = "";
+       /* Request the peer */
+-      tmp->chan = ast_request(tech, qe->chan->nativeformats, location, &status);
++      tmp->chan = ast_request(tech, qe->chan->nativeformats, location, &status, NULL);
+       if (!tmp->chan) {                       /* If we can't, just go on to the next call */
+ #if 0
+               ast_log(LOG_NOTICE, "Unable to create channel of type '%s' for Queue\n", cur->tech);
+@@ -1692,7 +1692,7 @@
+                                       if (option_verbose > 2)
+                                               ast_verbose(VERBOSE_PREFIX_3 "Now forwarding %s to '%s/%s' (thanks to %s)\n", in->name, tech, stuff, o->chan->name);
+                                       /* Setup parameters */
+-                                      o->chan = ast_request(tech, in->nativeformats, stuff, &status);
++                                      o->chan = ast_request(tech, in->nativeformats, stuff, &status, NULL);
+                                       if (status != o->oldstatus) 
+                                               update_dial_status(qe->parent, o->member, status);                                              
+                                       if (!o->chan) {
+diff -urN asterisk-1.2.4.orig/apps/app_readfile.c asterisk-1.2.4/apps/app_readfile.c
+--- asterisk-1.2.4.orig/apps/app_readfile.c    2005-11-29 19:24:39.000000000 +0100
++++ asterisk-1.2.4/apps/app_readfile.c 2006-01-31 09:41:43.000000000 +0100
+@@ -40,7 +40,7 @@
+ #include "asterisk/app.h"
+ #include "asterisk/module.h"
+-static char *tdesc = "Stores output of file into a variable";
++static char *tdesc = "Stores content of file into a variable";
+ static char *app_readfile = "ReadFile";
+diff -urN asterisk-1.2.4.orig/apps/app_segfault.c asterisk-1.2.4/apps/app_segfault.c
+--- asterisk-1.2.4.orig/apps/app_segfault.c    1970-01-01 01:00:00.000000000 +0100
++++ asterisk-1.2.4/apps/app_segfault.c 2006-01-31 09:41:43.000000000 +0100
+@@ -0,0 +1,75 @@
++/*
++ * Segfault application
++ * 
++ * An application to provoke a segmentation fault from the dialplan.
++ * (I know what you are thinking now...., but since Asterisk is too stable...
++ *  I needed something to test my failover switches.)
++ *
++ * Copyright (C) 2005 Junghanns.NET GmbH
++ * Klaus-Peter Junghanns <kpj@junghanns.net>
++ *
++ * This program is free software, distributed under the terms of
++ * the GNU General Public License. THIS APPLICATION _WILL_ CRASH YOUR
++ * ASTERISK SERVER SO OF COURSE THERE IS NOT LIABILITY FOR NOTHING!
++ */
++
++#include <stdlib.h>
++#include <unistd.h>
++#include <string.h>
++#include <stdio.h>
++#include <asterisk/lock.h>
++#include <asterisk/file.h>
++#include <asterisk/logger.h>
++#include <asterisk/channel.h>
++#include <asterisk/pbx.h>
++#include <asterisk/module.h>
++
++static char *tdesc = "Application for crashing Asterisk with a segmentation fault";
++
++static char *app = "Segfault";
++
++static char *synopsis = "This application will crash Asterisk with a segmentation fault.";
++
++static char *descrip = 
++"  Segfault():  Crash with a segfault. Never returns nufin.\n";
++
++STANDARD_LOCAL_USER;
++
++LOCAL_USER_DECL;
++
++static int segfault_exec(struct ast_channel *chan, void *data)
++{
++    struct localuser *u;
++    LOCAL_USER_ADD(u);
++    ((char *)0)[0] = 0;
++    LOCAL_USER_REMOVE(u);
++    return 0;
++}
++
++int unload_module(void)
++{
++    STANDARD_HANGUP_LOCALUSERS;
++    return ast_unregister_application(app);
++}
++
++int load_module(void)
++{
++    return ast_register_application(app, segfault_exec, synopsis, descrip);
++}
++
++char *description(void)
++{
++    return tdesc;
++}
++
++int usecount(void)
++{
++    int res;
++    STANDARD_USECOUNT(res);
++    return res;
++}
++
++char *key()
++{
++    return ASTERISK_GPL_KEY;
++}
+diff -urN asterisk-1.2.4.orig/apps/app_sms.c asterisk-1.2.4/apps/app_sms.c
+--- asterisk-1.2.4.orig/apps/app_sms.c 2005-12-26 19:19:12.000000000 +0100
++++ asterisk-1.2.4/apps/app_sms.c      2006-01-31 09:41:43.000000000 +0100
+@@ -1179,32 +1179,31 @@
+ {
+       struct ast_frame f = { 0 };
+       unsigned char waste[AST_FRIENDLY_OFFSET];
++#define MAXSAMPLES (800)
+ #ifdef OUTALAW
+-      unsigned char buf[800];
++      unsigned char buf[MAXSAMPLES];
+ #else
+-      signed short buf[800];
++      signed short buf[MAXSAMPLES];
+ #endif
++#define SAMPLE2LEN (sizeof (buf[0]))
+       sms_t *h = data;
+       int i;
+-      if (len > sizeof (buf)) {
+-              ast_log (LOG_WARNING, "Only doing %d bytes (%d bytes requested)\n", (int)(sizeof (buf) / sizeof (signed short)), len);
+-              len = sizeof (buf);
+-#ifdef OUTALAW
+-              samples = len;
+-#else
+-              samples = len / 2;
+-#endif
++      if (samples > MAXSAMPLES) {
++              ast_log (LOG_WARNING, "Only doing %d samples (%d requested)\n",
++                       MAXSAMPLES, samples);
++              samples = MAXSAMPLES;
+       }
+-      waste[0] = 0;                                    /* make compiler happy */
++      len = samples * SAMPLE2LEN;
++
++      waste[0] = 0;                            /* make compiler happy */
+       f.frametype = AST_FRAME_VOICE;
+ #ifdef OUTALAW
+       f.subclass = AST_FORMAT_ALAW;
+-      f.datalen = samples;
+ #else
+       f.subclass = AST_FORMAT_SLINEAR;
+-      f.datalen = samples * 2;
+ #endif
++      f.datalen = len;
+       f.offset = AST_FRIENDLY_OFFSET;
+       f.mallocd = 0;
+       f.data = buf;
+@@ -1256,6 +1255,8 @@
+               return -1;
+       }
+       return 0;
++#undef SAMPLE2LEN
++#undef MAXSAMPLES
+ }
+ static void sms_process (sms_t * h, int samples, signed short *data)
+diff -urN asterisk-1.2.4.orig/apps/app_zapras.c asterisk-1.2.4/apps/app_zapras.c
+--- asterisk-1.2.4.orig/apps/app_zapras.c      2005-11-29 19:24:39.000000000 +0100
++++ asterisk-1.2.4/apps/app_zapras.c   2006-01-31 09:41:43.000000000 +0100
+@@ -182,7 +182,7 @@
+                               }
+                       }
+                       /* Throw back into audio mode */
+-                      x = 1;
++                      x = 0;
+                       ioctl(chan->fds[0], ZT_AUDIOMODE, &x);
+                       /* Restore saved values */
+diff -urN asterisk-1.2.4.orig/asterisk.c asterisk-1.2.4/asterisk.c
+--- asterisk-1.2.4.orig/asterisk.c     2006-01-24 23:55:32.000000000 +0100
++++ asterisk-1.2.4/asterisk.c  2006-01-31 09:41:43.000000000 +0100
+@@ -221,6 +221,7 @@
+ char ast_config_AST_CTL_OWNER[AST_CONFIG_MAX_PATH] = "\0";
+ char ast_config_AST_CTL_GROUP[AST_CONFIG_MAX_PATH] = "\0";
+ char ast_config_AST_CTL[AST_CONFIG_MAX_PATH] = "asterisk.ctl";
++char ast_config_AST_SYMBOLIC_NAME[20];
+ static char *_argv[256];
+ static int shuttingdown = 0;
+@@ -1878,6 +1879,7 @@
+       ast_copy_string(ast_config_AST_PID, AST_PID, sizeof(ast_config_AST_PID));
+       ast_copy_string(ast_config_AST_SOCKET, AST_SOCKET, sizeof(ast_config_AST_SOCKET));
+       ast_copy_string(ast_config_AST_RUN_DIR, AST_RUN_DIR, sizeof(ast_config_AST_RUN_DIR));
++      ast_copy_string(ast_config_AST_SYMBOLIC_NAME, AST_SYMBOLIC_NAME, sizeof(ast_config_AST_SYMBOLIC_NAME));
+       /* no asterisk.conf? no problem, use buildtime config! */
+       if (!cfg) {
+@@ -1916,6 +1918,8 @@
+                       ast_copy_string(ast_config_AST_RUN_DIR, v->value, sizeof(ast_config_AST_RUN_DIR));
+               } else if (!strcasecmp(v->name, "astmoddir")) {
+                       ast_copy_string(ast_config_AST_MODULE_DIR, v->value, sizeof(ast_config_AST_MODULE_DIR));
++              } else if (!strcasecmp(v->name, "uniquename")) {
++                      strncpy(ast_config_AST_SYMBOLIC_NAME,v->value,sizeof(ast_config_AST_SYMBOLIC_NAME));
+               }
+               v = v->next;
+       }
+diff -urN asterisk-1.2.4.orig/build_tools/make_defaults_h asterisk-1.2.4/build_tools/make_defaults_h
+--- asterisk-1.2.4.orig/build_tools/make_defaults_h    2005-06-20 19:26:08.000000000 +0200
++++ asterisk-1.2.4/build_tools/make_defaults_h 2006-01-31 09:41:43.000000000 +0100
+@@ -16,6 +16,7 @@
+ #define AST_KEY_DIR    "${INSTALL_PATH}${ASTVARLIBDIR}/keys"
+ #define AST_DB         "${INSTALL_PATH}${ASTVARLIBDIR}/astdb"
+ #define AST_TMP_DIR    "${INSTALL_PATH}${ASTSPOOLDIR}/tmp"
++#define AST_SYMBOLIC_NAME     "asterisk"
+ #define AST_CONFIG_FILE "${INSTALL_PATH}${ASTCONFPATH}"
+diff -urN asterisk-1.2.4.orig/channel.c asterisk-1.2.4/channel.c
+--- asterisk-1.2.4.orig/channel.c      2006-01-25 10:46:43.000000000 +0100
++++ asterisk-1.2.4/channel.c   2006-01-31 09:41:43.000000000 +0100
+@@ -94,8 +94,8 @@
+  */
+ static int shutting_down = 0;
+-AST_MUTEX_DEFINE_STATIC(uniquelock);
+ static int uniqueint = 0;
++AST_MUTEX_DEFINE_EXPORTED(uniquelock);
+ unsigned long global_fin = 0, global_fout = 0;
+@@ -512,6 +512,17 @@
+       .description = "Null channel (should not see this)",
+ };
++char *ast_alloc_uniqueid(void) {
++      char *uniqueid;
++      uniqueid = malloc(64);
++      if (!uniqueid) return NULL;
++      ast_mutex_lock(&uniquelock);
++      snprintf(uniqueid, 63, "%s-%d-%li.%d", ast_config_AST_SYMBOLIC_NAME, ast_mainpid, (long)time(NULL), uniqueint++);
++      ast_mutex_unlock(&uniquelock);
++      return uniqueid;
++}
++
++
+ /*--- ast_channel_alloc: Create a new channel structure */
+ struct ast_channel *ast_channel_alloc(int needqueue)
+ {
+@@ -519,6 +530,7 @@
+       int x;
+       int flags;
+       struct varshead *headp;        
++      char *tmpuniqueid;
+               
+       /* If shutting down, don't allocate any new channels */
+@@ -584,9 +596,12 @@
+       tmp->data = NULL;
+       tmp->fin = global_fin;
+       tmp->fout = global_fout;
+-      ast_mutex_lock(&uniquelock);
+-      snprintf(tmp->uniqueid, sizeof(tmp->uniqueid), "%li.%d", (long) time(NULL), uniqueint++);
+-      ast_mutex_unlock(&uniquelock);
++      tmpuniqueid = ast_alloc_uniqueid();
++      snprintf(tmp->uniqueid, sizeof(tmp->uniqueid), tmpuniqueid);
++      if (tmpuniqueid) { 
++          free(tmpuniqueid);
++          tmpuniqueid = NULL;
++      }
+       headp = &tmp->varshead;
+       ast_mutex_init(&tmp->lock);
+       AST_LIST_HEAD_INIT_NOLOCK(headp);
+@@ -729,7 +744,7 @@
+  */
+ static struct ast_channel *channel_find_locked(const struct ast_channel *prev,
+                                              const char *name, const int namelen,
+-                                             const char *context, const char *exten)
++                                             const char *context, const char *exten, const char *uniqueid)
+ {
+       const char *msg = prev ? "deadlock" : "initial deadlock";
+       int retries, done;
+@@ -740,9 +755,14 @@
+               for (c = channels; c; c = c->next) {
+                       if (!prev) {
+                               /* want head of list */
+-                              if (!name && !exten)
++                              if (!name && !exten && !uniqueid)
+                                       break;
+-                              if (name) {
++                              if (uniqueid) {
++                                  if (!strcasecmp(c->uniqueid, uniqueid))
++                                      break;
++                                  else
++                                      continue;
++                              } else if (name) {
+                                       /* want match by full name */
+                                       if (!namelen) {
+                                               if (!strcasecmp(c->name, name))
+@@ -793,33 +813,39 @@
+ /*--- ast_channel_walk_locked: Browse channels in use */
+ struct ast_channel *ast_channel_walk_locked(const struct ast_channel *prev)
+ {
+-      return channel_find_locked(prev, NULL, 0, NULL, NULL);
++      return channel_find_locked(prev, NULL, 0, NULL, NULL, NULL);
+ }
+ /*--- ast_get_channel_by_name_locked: Get channel by name and lock it */
+ struct ast_channel *ast_get_channel_by_name_locked(const char *name)
+ {
+-      return channel_find_locked(NULL, name, 0, NULL, NULL);
++      return channel_find_locked(NULL, name, 0, NULL, NULL, NULL);
+ }
+ /*--- ast_get_channel_by_name_prefix_locked: Get channel by name prefix and lock it */
+ struct ast_channel *ast_get_channel_by_name_prefix_locked(const char *name, const int namelen)
+ {
+-      return channel_find_locked(NULL, name, namelen, NULL, NULL);
++      return channel_find_locked(NULL, name, namelen, NULL, NULL, NULL);
+ }
+ /*--- ast_walk_channel_by_name_prefix_locked: Get next channel by name prefix and lock it */
+ struct ast_channel *ast_walk_channel_by_name_prefix_locked(struct ast_channel *chan, const char *name, const int namelen)
+ {
+-      return channel_find_locked(chan, name, namelen, NULL, NULL);
++      return channel_find_locked(chan, name, namelen, NULL, NULL, NULL);
+ }
+ /*--- ast_get_channel_by_exten_locked: Get channel by exten (and optionally context) and lock it */
+ struct ast_channel *ast_get_channel_by_exten_locked(const char *exten, const char *context)
+ {
+-      return channel_find_locked(NULL, NULL, 0, context, exten);
++      return channel_find_locked(NULL, NULL, 0, context, exten, NULL);
+ }
++struct ast_channel *ast_get_channel_by_uniqueid_locked(const char *uniqueid)
++{
++      return channel_find_locked(NULL, NULL, 0, NULL, NULL, uniqueid);
++}
++
++
+ /*--- ast_safe_sleep_conditional: Wait, look for hangups and condition arg */
+ int ast_safe_sleep_conditional(       struct ast_channel *chan, int ms,
+       int (*cond)(void*), void *data )
+@@ -912,8 +938,10 @@
+               free(chan->tech_pvt);
+       }
+-      if (chan->sched)
+-              sched_context_destroy(chan->sched);
++      if (chan->sched) {
++              sched_context_destroy(chan->sched);     
++              chan->sched = NULL;
++      }
+       ast_copy_string(name, chan->name, sizeof(name));
+@@ -956,10 +984,11 @@
+       while ((vardata = AST_LIST_REMOVE_HEAD(headp, entries)))
+               ast_var_delete(vardata);
++
+       free(chan);
+       ast_mutex_unlock(&chlock);
+-      ast_device_state_changed_literal(name);
++      ast_device_state_changed_literal(name, NULL, NULL);
+ }
+ int ast_channel_spy_add(struct ast_channel *chan, struct ast_channel_spy *spy)
+@@ -2364,7 +2393,7 @@
+                         &chan->writetrans, 1);
+ }
+-struct ast_channel *__ast_request_and_dial(const char *type, int format, void *data, int timeout, int *outstate, const char *cid_num, const char *cid_name, struct outgoing_helper *oh)
++struct ast_channel *__ast_request_and_dial(const char *type, int format, void *data, int timeout, int *outstate, int callingpres, const char *cid_num, const char *cid_name, struct outgoing_helper *oh, char* uniqueid)
+ {
+       int state = 0;
+       int cause = 0;
+@@ -2372,7 +2401,7 @@
+       struct ast_frame *f;
+       int res = 0;
+       
+-      chan = ast_request(type, format, data, &cause);
++      chan = ast_request(type, format, data, &cause, uniqueid);
+       if (chan) {
+               if (oh) {
+                       if (oh->vars)   
+@@ -2384,6 +2413,7 @@
+               }
+               ast_set_callerid(chan, cid_num, cid_name, cid_num);
++              chan->cid.cid_pres = callingpres;
+               if (!ast_call(chan, data, 0)) {
+                       while(timeout && (chan->_state != AST_STATE_UP)) {
+                               res = ast_waitfor(chan, timeout);
+@@ -2406,6 +2436,7 @@
+                                       if (f->subclass == AST_CONTROL_RINGING)
+                                               state = AST_CONTROL_RINGING;
+                                       else if ((f->subclass == AST_CONTROL_BUSY) || (f->subclass == AST_CONTROL_CONGESTION)) {
++                                              res = 0;
+                                               state = f->subclass;
+                                               ast_frfree(f);
+                                               break;
+@@ -2475,12 +2506,12 @@
+       return chan;
+ }
+-struct ast_channel *ast_request_and_dial(const char *type, int format, void *data, int timeout, int *outstate, const char *cidnum, const char *cidname)
++struct ast_channel *ast_request_and_dial(const char *type, int format, void *data, int timeout, int *outstate, int callingpres, const char *cidnum, const char *cidname, char *uniqueid)
+ {
+-      return __ast_request_and_dial(type, format, data, timeout, outstate, cidnum, cidname, NULL);
++      return __ast_request_and_dial(type, format, data, timeout, outstate, 0, cidnum, cidname, NULL, uniqueid);
+ }
+-struct ast_channel *ast_request(const char *type, int format, void *data, int *cause)
++struct ast_channel *ast_request(const char *type, int format, void *data, int *cause, char *uniqueid)
+ {
+       struct chanlist *chan;
+       struct ast_channel *c;
+@@ -2517,6 +2548,7 @@
+               if (!(c = chan->tech->requester(type, capabilities, data, cause)))
+                       return NULL;
++              if (uniqueid) strncpy(c->uniqueid, uniqueid, sizeof(c->uniqueid));
+               if (c->_state == AST_STATE_DOWN) {
+                       manager_event(EVENT_FLAG_CALL, "Newchannel",
+                                     "Channel: %s\r\n"
+@@ -2764,6 +2796,29 @@
+       return res;
+ }
++int ast_channel_masquerade_locked(struct ast_channel *original, struct ast_channel *clone)
++{
++      struct ast_frame null = { AST_FRAME_NULL, };
++      int res = -1;
++      ast_log(LOG_DEBUG, "Planning to masquerade %s into the structure of %s\n",
++              clone->name, original->name);
++      if (original->masq) {
++              ast_log(LOG_WARNING, "%s is already going to masquerade as %s\n", 
++                      original->masq->name, original->name);
++      } else if (clone->masqr) {
++              ast_log(LOG_WARNING, "%s is already going to masquerade as %s\n", 
++                      clone->name, clone->masqr->name);
++      } else {
++              original->masq = clone;
++              clone->masqr = original;
++              ast_queue_frame(original, &null);
++              ast_queue_frame(clone, &null);
++              ast_log(LOG_DEBUG, "Done planning to masquerade %s into the structure of %s\n", original->name, clone->name);
++              res = 0;
++      }
++      return res;
++}
++
+ void ast_change_name(struct ast_channel *chan, char *newname)
+ {
+       char tmp[256];
+@@ -3130,15 +3185,14 @@
+                               );
+ }
+-int ast_setstate(struct ast_channel *chan, int state)
+-{
++int ast_setstate_and_cid(struct ast_channel *chan, int state, char *cid_num, char *cid_name) {
+       int oldstate = chan->_state;
+       if (oldstate == state)
+               return 0;
+       chan->_state = state;
+-      ast_device_state_changed_literal(chan->name);
++      ast_device_state_changed_literal(chan->name, cid_num, cid_name);
+       manager_event(EVENT_FLAG_CALL,
+                     (oldstate == AST_STATE_DOWN) ? "Newchannel" : "Newstate",
+                     "Channel: %s\r\n"
+@@ -3154,6 +3208,10 @@
+       return 0;
+ }
++int ast_setstate(struct ast_channel *chan, int state) {
++    return ast_setstate_and_cid(chan, state, NULL, NULL);
++}
++
+ /*--- Find bridged channel */
+ struct ast_channel *ast_bridged_channel(struct ast_channel *chan)
+ {
+@@ -3331,6 +3389,7 @@
+       char callee_warning = 0;
+       int to;
++
+       if (c0->_bridge) {
+               ast_log(LOG_WARNING, "%s is already in a bridge with %s\n", 
+                       c0->name, c0->_bridge->name);
+@@ -3341,6 +3400,10 @@
+                       c1->name, c1->_bridge->name);
+               return -1;
+       }
++
++      if (IS_DIGITAL(c0->transfercapability) || IS_DIGITAL(c1->transfercapability)) {
++          config->flags = 0;
++      }
+       
+       /* Stop if we're a zombie or need a soft hangup */
+       if (ast_test_flag(c0, AST_FLAG_ZOMBIE) || ast_check_hangup_locked(c0) ||
+diff -urN asterisk-1.2.4.orig/channels/Makefile asterisk-1.2.4/channels/Makefile
+--- asterisk-1.2.4.orig/channels/Makefile      2005-12-15 11:52:30.000000000 +0100
++++ asterisk-1.2.4/channels/Makefile   2006-01-31 09:41:43.000000000 +0100
+@@ -122,6 +122,35 @@
+ endif
+ endif # WITHOUT_ZAPTEL
++ifneq ($(wildcard $(CROSS_COMPILE_TARGET)/usr/include/capi20.h)$(wildcard $(CROSS_COMPILE_TARGET)/usr/local/include/capi20.h),)
++  CHANNEL_LIBS+=chan_capi.so
++# uncomment the following line if you really never ever want early b3 connects,
++# you can also configure it in the dialstring, this is just for performance
++# NOTE: this is probably obsolete by using the "R" dial option
++#CFLAGS+=-DCAPI_NEVER_EVER_EARLY_B3_CONNECTS
++
++# uncommnet next line to force dtmf software detection/generation, can also be configured
++# in capi.conf on a perdevice basis (softdtmf=1)
++#CFLAGS+=-DCAPI_FORCE_SOFTWARE_DTMF
++
++# uncomment the next line if you are in the ulaw world
++#CFLAGS+=-DCAPI_ULAW
++
++# very experimental echo squelching
++CFLAGS+=-DCAPI_ES
++
++#gains
++CFLAGS+=-DCAPI_GAIN
++
++# what do to with call waiting connect indications?
++# uncomment the next line for call deflection in that case
++CFLAGS+=-DCAPI_DEFLECT_ON_CIRCUITBUSY
++
++# audio sync
++CFLAGS+=-DCAPI_SYNC
++
++endif
++
+ ifneq ($(wildcard $(CROSS_COMPILE_TARGET)/usr/include/vpbapi.h),)
+   CHANNEL_LIBS+=chan_vpb.so
+   CFLAGS+=-DLINUX
+@@ -220,6 +249,9 @@
+ chan_nbs.so: chan_nbs.o
+       $(CC) $(SOLINK) -o $@ $< -lnbs
++chan_capi.so: chan_capi.o
++      $(CC) $(SOLINK) -o $@ $< -lcapi20
++
+ chan_vpb.o: chan_vpb.c
+       $(CXX) -c $(CFLAGS) -o $@ chan_vpb.c
+diff -urN asterisk-1.2.4.orig/channels/chan_agent.c asterisk-1.2.4/channels/chan_agent.c
+--- asterisk-1.2.4.orig/channels/chan_agent.c  2006-01-13 07:07:39.000000000 +0100
++++ asterisk-1.2.4/channels/chan_agent.c       2006-01-31 09:41:43.000000000 +0100
+@@ -1331,7 +1331,7 @@
+                                               chan = agent_new(p, AST_STATE_DOWN);
+                                       } else if (!p->owner && !ast_strlen_zero(p->loginchan)) {
+                                               /* Adjustable agent */
+-                                              p->chan = ast_request("Local", format, p->loginchan, cause);
++                                              p->chan = ast_request("Local", format, p->loginchan, cause, NULL);
+                                               if (p->chan)
+                                                       chan = agent_new(p, AST_STATE_DOWN);
+                                       }
+diff -urN asterisk-1.2.4.orig/channels/chan_capi.c asterisk-1.2.4/channels/chan_capi.c
+--- asterisk-1.2.4.orig/channels/chan_capi.c   1970-01-01 01:00:00.000000000 +0100
++++ asterisk-1.2.4/channels/chan_capi.c        2006-01-31 09:41:43.000000000 +0100
+@@ -0,0 +1,2888 @@
++/*
++ * (CAPI*)
++ *
++ * An implementation of Common ISDN API 2.0 for Asterisk
++ *
++ * Copyright (C) 2002, 2003, 2004, 2005 Junghanns.NET GmbH
++ *
++ * Klaus-Peter Junghanns <kapejod@ns1.jnetdns.de>
++ *
++ * This program is free software and may be modified and 
++ * distributed under the terms of the GNU Public License.
++ */
++
++#include <sys/time.h>
++#include <sys/signal.h>
++#include <stdlib.h>
++#include <stdio.h>
++#include <string.h>
++#include <errno.h>
++#include <unistd.h>
++#include <fcntl.h>
++#include <sys/types.h>
++#include <asterisk/lock.h>
++#include <asterisk/frame.h> 
++#include <asterisk/channel.h>
++#include <asterisk/logger.h>
++#include <asterisk/module.h>
++#include <asterisk/pbx.h>
++#include <asterisk/config.h>
++#include <asterisk/options.h>
++#include <asterisk/features.h>
++#include <asterisk/utils.h>
++#include <asterisk/cli.h>
++#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined( __NetBSD__ ) || defined(__APPLE__)
++#include <capi_bsd.h>
++#else
++#include <linux/capi.h>
++#endif
++#include <capi20.h>
++#include <asterisk/dsp.h>
++#include <asterisk/xlaw.h>
++#include <asterisk/chan_capi.h>
++
++unsigned ast_capi_ApplID;
++_cword ast_capi_MessageNumber=1;
++static char desc[] = "Common ISDN API for Asterisk";
++#ifdef CAPI_ULAW
++static char tdesc[] = "Common ISDN API Driver (0.4.0) muLaw";
++#else
++static char tdesc[] = "Common ISDN API Driver (0.4.0) aLaw ";
++#endif
++static char type[] = "CAPI";
++
++
++static int usecnt;
++AST_MUTEX_DEFINE_STATIC(usecnt_lock);
++AST_MUTEX_DEFINE_STATIC(iflock);
++AST_MUTEX_DEFINE_STATIC(pipelock);
++AST_MUTEX_DEFINE_STATIC(monlock);
++AST_MUTEX_DEFINE_STATIC(contrlock);
++AST_MUTEX_DEFINE_STATIC(capi_send_buffer_lock);
++AST_MUTEX_DEFINE_STATIC(capi_put_lock);
++
++#ifdef CAPI_ULAW
++static int capi_capability = AST_FORMAT_ULAW;
++#else
++static int capi_capability = AST_FORMAT_ALAW;
++#endif
++
++#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined( __NetBSD__ ) || defined(__APPLE__)
++static CAPIProfileBuffer_t profile;
++#else
++static struct ast_capi_profile profile;
++#endif
++static pthread_t monitor_thread = -1;
++
++static struct ast_capi_pvt *iflist = NULL;
++static struct capi_pipe *pipelist = NULL;
++static int capi_last_plci = 0;
++static struct ast_capi_controller *capi_controllers[AST_CAPI_MAX_CONTROLLERS];
++static int capi_num_controllers = 0;
++static int capi_counter = 0;
++static unsigned long capi_used_controllers=0;
++
++static char capi_send_buffer[AST_CAPI_MAX_B3_BLOCKS * AST_CAPI_MAX_B3_BLOCK_SIZE];
++static int capi_send_buffer_handle = 0;
++
++char capi_national_prefix[AST_MAX_EXTENSION];
++char capi_international_prefix[AST_MAX_EXTENSION];
++
++int capidebug = 0;
++
++static const struct ast_channel_tech capi_tech;
++
++MESSAGE_EXCHANGE_ERROR _capi_put_cmsg(_cmsg *CMSG) {
++    MESSAGE_EXCHANGE_ERROR error;
++    if (ast_mutex_lock(&capi_put_lock)) {
++        ast_log(LOG_WARNING,"Unable to lock capi put!\n");
++        return -1;
++    } 
++    error = capi20_put_cmsg(CMSG);    
++    if (ast_mutex_unlock(&capi_put_lock)) {
++      ast_log(LOG_WARNING,"Unable to unlock capi put!\n");
++        return -1;
++    }
++    return error;
++}
++
++
++MESSAGE_EXCHANGE_ERROR check_wait_get_cmsg(_cmsg *CMSG) {
++    MESSAGE_EXCHANGE_ERROR Info;
++    struct timeval tv;
++    tv.tv_sec = 0;
++    tv.tv_usec = 10000;
++    Info = capi20_waitformessage(ast_capi_ApplID,&tv);
++    if ((Info != 0x0000) && (Info != 0x1104)) {
++      if (capidebug) {
++          ast_log(LOG_DEBUG, "Error waiting for cmsg... INFO = %#x\n", Info);
++      }
++      return Info;
++    }
++    
++    if (Info == 0x0000) {
++        Info = capi_get_cmsg(CMSG,ast_capi_ApplID);
++    }
++    return Info;
++}
++
++
++unsigned ListenOnController(unsigned long CIPmask,unsigned controller) {
++    MESSAGE_EXCHANGE_ERROR  error;
++    _cmsg                 CMSG,CMSG2;
++
++    LISTEN_REQ_HEADER(&CMSG, ast_capi_ApplID, ast_capi_MessageNumber++, controller);
++#ifdef CAPI_NEVER_EVER_EARLY_B3_CONNECTS
++    LISTEN_REQ_INFOMASK(&CMSG) = 0x00ff; // lots of info ;)
++#else
++    LISTEN_REQ_INFOMASK(&CMSG) = 0x03ff; // lots of info ;) + early B3 connect
++#endif
++    LISTEN_REQ_CIPMASK(&CMSG) = CIPmask;
++    if ((error = _capi_put_cmsg(&CMSG)) != 0) {
++      return error;
++    }
++    while (!IS_LISTEN_CONF(&CMSG2)) {
++      error = check_wait_get_cmsg(&CMSG2);
++    }
++    return 0;
++}
++
++// Echo cancellation is for cards w/ integrated echo cancellation only
++// (i.e. Eicon active cards support it)
++
++#define EC_FUNCTION_ENABLE            1
++#define EC_FUNCTION_DISABLE           2
++#define EC_FUNCTION_FREEZE            3
++#define EC_FUNCTION_RESUME            4
++#define EC_FUNCTION_RESET             5
++#define EC_OPTION_DISABLE_NEVER               0
++#define EC_OPTION_DISABLE_G165                (1<<1)
++#define EC_OPTION_DISABLE_G164_OR_G165        (1<<1 | 1<<2)
++#define EC_DEFAULT_TAIL                       64
++
++static int capi_echo_canceller(struct ast_channel *c, int function) {
++    struct ast_capi_pvt *i = c->tech_pvt;
++    MESSAGE_EXCHANGE_ERROR  error;
++    _cmsg                 CMSG;
++    unsigned char   buf[7];
++
++      /* If echo cancellation is not requested or supported, don't attempt to enable it */
++      ast_mutex_lock(&contrlock);
++      if (!capi_controllers[i->controller]->echocancel || !i->doEC) {
++              ast_mutex_unlock(&contrlock);
++              return 0;
++      }
++      ast_mutex_unlock(&contrlock);
++
++      if (option_verbose > 2) 
++              ast_verbose(VERBOSE_PREFIX_3 "Setting up echo canceller (PLCI=%#x, function=%d, options=%d, tail=%d)\n",i->PLCI,function,i->ecOption,i->ecTail);
++
++      FACILITY_REQ_HEADER(&CMSG, ast_capi_ApplID, ast_capi_MessageNumber++, 0);
++      FACILITY_REQ_NCCI(&CMSG) = i->NCCI;
++      FACILITY_REQ_FACILITYSELECTOR(&CMSG) = 6; /* Echo canceller */
++
++        buf[0]=6; /* msg size */
++        buf[1]=function;
++      if (function == EC_FUNCTION_ENABLE) {
++              buf[3]=i->ecOption; /* bit field - ignore echo canceller disable tone */
++              buf[5]=i->ecTail;   /* Tail length, ms */
++      }
++      else {
++              buf[3]=0;
++              buf[5]=0;
++      }
++
++      // Always null:
++        buf[2]=0;
++        buf[4]=0;
++        buf[6]=0;
++
++      FACILITY_REQ_FACILITYREQUESTPARAMETER(&CMSG) = buf;
++        
++      if ((error = _capi_put_cmsg(&CMSG)) != 0) {
++          ast_log(LOG_ERROR,"error sending FACILITY_REQ (error=%#x)\n",error);
++          return error;
++      }
++
++      if (option_verbose > 5) 
++         ast_verbose(VERBOSE_PREFIX_4 "sent FACILITY_REQ (PLCI=%#x)\n",i->PLCI);
++
++    return 0;
++}
++
++int capi_detect_dtmf(struct ast_channel *c, int flag) {
++    struct ast_capi_pvt *i = c->tech_pvt;
++#ifndef CAPI_FORCE_SOFTWARE_DTMF
++    MESSAGE_EXCHANGE_ERROR  error;
++    _cmsg                 CMSG;
++    unsigned char buf[9];
++    // does the controller support dtmf? and do we want to use it?
++    ast_mutex_lock(&contrlock);
++    if ((capi_controllers[i->controller]->dtmf == 1) && (i->doDTMF == 0)) {
++      ast_mutex_unlock(&contrlock);
++      FACILITY_REQ_HEADER(&CMSG, ast_capi_ApplID, ast_capi_MessageNumber++, 0);
++      FACILITY_REQ_PLCI(&CMSG) = i->PLCI;
++      FACILITY_REQ_FACILITYSELECTOR(&CMSG) = 1;
++      buf[0] = 8;
++      if (flag == 1) {
++          buf[1] = 1;
++      } else {
++          buf[1] = 2;
++      }
++      buf[2] = 0;
++      buf[3] = AST_CAPI_DTMF_DURATION;
++      buf[4] = 0;
++      buf[5] = AST_CAPI_DTMF_DURATION;
++      buf[6] = 0;
++      buf[7] = 0;
++      buf[8] = 0;
++      FACILITY_REQ_FACILITYREQUESTPARAMETER(&CMSG) = buf;
++        
++      if ((error = _capi_put_cmsg(&CMSG)) != 0) {
++          ast_log(LOG_ERROR,"error sending FACILITY_REQ (error=%#x)\n",error);
++          return error;
++      } else {
++          if (option_verbose > 5) {
++              ast_verbose(VERBOSE_PREFIX_4 "sent FACILITY_REQ (PLCI=%#x)\n",i->PLCI);
++          }
++      }
++    } else {
++      ast_mutex_unlock(&contrlock);
++
++#endif
++      // do software dtmf detection
++      i->doDTMF = 1; // just being paranoid again...
++#ifndef CAPI_FORCE_SOFTWARE_DTMF
++    }
++#endif
++    return 0;
++}
++static int capi_send_digit(struct ast_channel *c,char digit) {
++    struct ast_capi_pvt *i = c->tech_pvt;
++    MESSAGE_EXCHANGE_ERROR  error;
++    _cmsg                 CMSG;
++    unsigned char     buf[10];
++    
++    if (i->state != CAPI_STATE_BCONNECTED) {
++      return 0;
++    }
++    
++    
++#ifndef CAPI_NEVER_EVER_EARLY_B3_CONNECTS
++    if(i->earlyB3 == 1)
++    /* we should really test for the network saying the number is incomplete
++    since i'm only doing a test and this is true at the right time
++    i'm going with this */
++    {
++
++      INFO_REQ_HEADER(&CMSG, ast_capi_ApplID, ast_capi_MessageNumber++, 0);
++      INFO_REQ_PLCI(&CMSG) = i->PLCI;
++      buf[0] = 2;
++      buf[1] = 0x80;
++      buf[2] = digit;
++      INFO_REQ_CALLEDPARTYNUMBER(&CMSG) = buf;
++
++
++      if ((error = _capi_put_cmsg(&CMSG)) != 0) {
++          ast_log(LOG_ERROR,"error sending CALLEDPARTYNUMBER INFO (error=%#x)\n",error);
++          return error;
++      } else {
++          if (option_verbose > 5) {
++              ast_verbose(VERBOSE_PREFIX_4 "sent CALLEDPARTYNUMBER INFO digit = %c (PLCI=%#x)\n", digit, i->PLCI);
++          }
++      }
++
++    } else {
++#endif
++#ifndef CAPI_FORCE_SOFTWARE_DTMF
++      ast_mutex_lock(&contrlock);
++      if ((capi_controllers[i->controller]->dtmf == 0) || (i->doDTMF == 1)) {
++#endif
++          // let * fake it
++#ifndef CAPI_FORCE_SOFTWARE_DTMF
++          ast_mutex_unlock(&contrlock);
++#endif
++          return -1;
++#ifndef CAPI_FORCE_SOFTWARE_DTMF
++      }
++      ast_mutex_unlock(&contrlock);
++      
++      FACILITY_REQ_HEADER(&CMSG, ast_capi_ApplID, ast_capi_MessageNumber++, 0);
++      FACILITY_REQ_PLCI(&CMSG) = i->NCCI;
++        FACILITY_REQ_FACILITYSELECTOR(&CMSG) = 1;
++        buf[0] = 8;
++    
++        buf[1] = 3;
++        buf[2] = 0;
++    
++        buf[3] = AST_CAPI_DTMF_DURATION;
++        buf[4] = 0;
++    
++        buf[5] = AST_CAPI_DTMF_DURATION;
++        buf[6] = 0;
++    
++        buf[7] = 1;
++      buf[8] = digit;
++        buf[9] = 0;
++      FACILITY_REQ_FACILITYREQUESTPARAMETER(&CMSG) = buf;
++        
++        if ((error = _capi_put_cmsg(&CMSG)) != 0) {
++          ast_log(LOG_ERROR,"error sending FACILITY_REQ (error=%#x)\n",error);
++          return error;
++        } else {
++          if (option_verbose > 4) {
++              ast_verbose(VERBOSE_PREFIX_3 "sent dtmf '%c'\n",digit);
++          }
++      }
++#endif
++#ifndef CAPI_NEVER_EVER_EARLY_B3_CONNECTS
++    }
++#endif
++    return 0;
++}
++
++static int capi_alert(struct ast_channel *c) {
++    struct ast_capi_pvt *i = c->tech_pvt;
++    MESSAGE_EXCHANGE_ERROR  error;
++    _cmsg     CMSG;
++    
++    ALERT_REQ_HEADER(&CMSG, ast_capi_ApplID, i->MessageNumber, 0);
++    ALERT_REQ_PLCI(&CMSG) = i->PLCI;
++
++    if ((error = _capi_put_cmsg(&CMSG)) != 0) {
++      ast_log(LOG_ERROR,"error sending ALERT_REQ PLCI = %#x\n",i->PLCI);
++      return -1;
++    } else {
++      if (option_verbose > 5) {
++          ast_verbose(VERBOSE_PREFIX_4 "sent ALERT_REQ PLCI = %#x\n",i->PLCI);
++      }
++    }
++
++    i->state = CAPI_STATE_ALERTING;
++    return 0;
++}
++
++#ifdef CAPI_DEFLECT_ON_CIRCUITBUSY
++static int capi_deflect(struct ast_channel *chan, void *data)
++{
++    struct ast_capi_pvt *i = chan->tech_pvt;
++    MESSAGE_EXCHANGE_ERROR Info;
++    _cmsg     CMSG;
++    char      bchaninfo[1];
++    char      fac[60];
++    int res=0;
++    int ms=3000;
++
++    if (!data) {
++      ast_log(LOG_WARNING, "cd requires an argument (destination phone number)\n");
++      return -1;
++    }
++
++    if ((i->state == CAPI_STATE_CONNECTED) || (i->state == CAPI_STATE_BCONNECTED)) {
++      ast_log(LOG_ERROR, "call deflection does not work with calls that are already connected!\n");
++      return -1;
++    }
++    // wait until the channel is alerting, so we dont drop the call and interfer with msgs
++    while ((ms > 0) && (i->state != CAPI_STATE_ALERTING)) {
++      sleep(100);
++      ms -= 100;
++    }
++
++    // make sure we hang up correctly
++    i->state = CAPI_STATE_CONNECTPENDING;
++
++    fac[0]=0; // len 
++    fac[1]=0; //len 
++    fac[2]=0x01; // Use D-Chan
++    fac[3]=0; // Keypad len
++    fac[4]=31;        // user user data? len = 31 = 29 + 2
++    fac[5]=0x1c;      // magic?
++    fac[6]=0x1d;      // strlen destination + 18 = 29
++    fac[7]=0x91;      // ..
++    fac[8]=0xA1;
++    fac[9]=0x1A;      // strlen destination + 15 = 26
++    fac[10]=0x02;
++    fac[11]=0x01;
++    fac[12]=0x70;
++    fac[13]=0x02;
++    fac[14]=0x01;
++    fac[15]=0x0d;
++    fac[16]=0x30;
++    fac[17]=0x12;     // strlen destination + 7 = 18
++    fac[18]=0x30;     // ...hm 0x30
++    fac[19]=0x0d;     // strlen destination + 2       
++    fac[20]=0x80;     // CLIP
++    fac[21]=0x0b;     //  strlen destination 
++    fac[22]=0x01;     //  destination start
++    fac[23]=0x01;     //  
++    fac[24]=0x01;     //  
++    fac[25]=0x01;     //  
++    fac[26]=0x01;     //  
++    fac[27]=0x01;     //  
++    fac[28]=0x01;     //  
++    fac[29]=0x01;     //  
++    fac[30]=0x01;     //  
++    fac[31]=0x01;     //  
++    fac[32]=0x01;     //  
++    fac[33]=0x01;     // 0x1 = sending complete
++    fac[34]=0x01;
++    fac[35]=0x01;
++                                 
++    memcpy((unsigned char *)fac+22,data,strlen(data));
++    fac[22+strlen(data)]=0x01;        // fill with 0x01 if number is only 6 numbers (local call)
++    fac[23+strlen(data)]=0x01;
++    fac[24+strlen(data)]=0x01;
++    fac[25+strlen(data)]=0x01;
++    fac[26+strlen(data)]=0x01;
++     
++    fac[6]=18+strlen(data);
++    fac[9]=15+strlen(data);
++    fac[17]=7+strlen(data);
++    fac[19]=2+strlen(data);
++    fac[21]=strlen(data);
++
++    bchaninfo[0] = 0x1;
++    INFO_REQ_HEADER(&CMSG,ast_capi_ApplID,ast_capi_MessageNumber++,0);
++    INFO_REQ_CONTROLLER(&CMSG) = i->controller;
++    INFO_REQ_PLCI(&CMSG) = i->PLCI;
++    INFO_REQ_BCHANNELINFORMATION(&CMSG) = (unsigned char*)bchaninfo; // use D-Channel
++    INFO_REQ_KEYPADFACILITY(&CMSG) = 0;
++    INFO_REQ_USERUSERDATA(&CMSG) = 0;
++    INFO_REQ_FACILITYDATAARRAY(&CMSG) = (unsigned char*) fac + 4;
++
++    if ((Info = _capi_put_cmsg(&CMSG)) != 0) {
++      ast_log(LOG_ERROR,"Error sending INFO_REQ\n");
++      return Info;
++    } else {
++      if (capidebug) {
++          // ast_log(LOG_NOTICE,"%s\n",capi_cmsg2str(&CMSG));
++          ast_log(LOG_NOTICE,"sent INFO_REQ PLCI = %#x\n",i->PLCI);
++      }
++    }
++
++    return res;
++}
++#endif
++
++void remove_pipe(int PLCI) {
++    struct capi_pipe *p,*ptmp;
++
++    ast_mutex_lock(&pipelock);
++    p = pipelist;
++    ptmp = NULL;
++    while (p) {
++      if (p->PLCI == PLCI) {
++          if (ptmp == NULL) {
++              // mypipe == head of pipelist
++              pipelist = p->next;
++              if(p->fd > -1) close(p->fd);
++              if(p->i != NULL && p->i->fd > -1) close(p->i->fd);
++              free(p);
++              if (option_verbose > 4) {
++                  ast_verbose(VERBOSE_PREFIX_3 "removed pipe for PLCI = %#x\n",PLCI);
++              }
++              break;
++          } else {
++              // somehwere inbetween or at the end
++              ptmp->next = p->next;
++              if (p->next == NULL) {
++                  capi_last_plci = p->PLCI;
++              }
++              if(p->fd > -1) close(p->fd);
++              if(p->i != NULL && p->i->fd > -1) close(p->i->fd);
++              free(p);
++              if (option_verbose > 4) {
++                  ast_verbose(VERBOSE_PREFIX_3 "removed pipe for PLCI = %#x\n",PLCI);
++              }
++              break;
++          }
++      }
++      ptmp = p;
++      p = p->next;
++    }
++    ast_mutex_unlock(&pipelock);
++}
++
++static int capi_activehangup(struct ast_channel *c) {
++    struct ast_capi_pvt *i = c->tech_pvt;
++    MESSAGE_EXCHANGE_ERROR  error;
++    _cmsg     CMSG;
++
++    if (option_verbose > 2) {
++      if (capidebug)
++            ast_verbose(VERBOSE_PREFIX_4 "activehangingup\n");
++    }
++
++    if (i == NULL) {
++      return 0;
++    }
++
++    if (c->_state == AST_STATE_RING) {
++      CONNECT_RESP_HEADER(&CMSG, ast_capi_ApplID, i->MessageNumber, 0);
++      CONNECT_RESP_PLCI(&CMSG) = i->PLCI;
++      CONNECT_RESP_REJECT(&CMSG) = 2;
++      if ((error = _capi_put_cmsg(&CMSG)) != 0) {
++          ast_log(LOG_ERROR,"error sending CONNECT_RESP for PLCI = %#x\n",i->PLCI);
++      } else {
++          if (option_verbose > 5) {
++              ast_verbose(VERBOSE_PREFIX_4 "sent CONNECT_RESP for PLCI = %#x\n",i->PLCI);
++          }
++      }
++      return 0;
++    }
++
++    // active disconnect
++    if (i->state == CAPI_STATE_BCONNECTED) {
++      DISCONNECT_B3_REQ_HEADER(&CMSG, ast_capi_ApplID, ast_capi_MessageNumber++, 0);
++      DISCONNECT_B3_REQ_NCCI(&CMSG) = i->NCCI;
++
++      if ((error = _capi_put_cmsg(&CMSG)) != 0) {
++          ast_log(LOG_ERROR, "error sending DISCONNECT_B3_REQ NCCI=%#x\n",i->NCCI);
++      } else {
++          if (option_verbose > 5) {
++              ast_verbose(VERBOSE_PREFIX_4 "sent DISCONNECT_B3_REQ NCCI=%#x\n",i->NCCI);
++          }
++      }
++      // wait for the B3 layer to go down
++      while (i->state != CAPI_STATE_CONNECTED) {
++          usleep(10000);
++      }
++    }
++    if ((i->state == CAPI_STATE_CONNECTED) || (i->state == CAPI_STATE_CONNECTPENDING)){
++      DISCONNECT_REQ_HEADER(&CMSG, ast_capi_ApplID, ast_capi_MessageNumber++, 0);
++      DISCONNECT_REQ_PLCI(&CMSG) = i->PLCI;
++
++      if ((error = _capi_put_cmsg(&CMSG)) != 0) {
++          ast_log(LOG_ERROR, "error sending DISCONNECT_REQ PLCI=%#x\n",i->PLCI);
++      } else {
++          if (option_verbose > 5) {
++              ast_verbose(VERBOSE_PREFIX_4 "sent DISCONNECT_REQ PLCI=%#x\n",i->PLCI);
++          }
++      }
++      // wait for the B1 layer to go down
++      while (i->state != CAPI_STATE_DISCONNECTED) {
++          usleep(10000);
++      }
++    }
++    return 0;
++}
++
++static int capi_hangup(struct ast_channel *c) {
++    struct ast_capi_pvt *i = c->tech_pvt;
++
++    // hmm....ok...this is called to free the capi interface (passive disconnect)
++    // or to bring down the channel (active disconnect)
++    
++    if (option_verbose > 3)
++          ast_verbose(VERBOSE_PREFIX_3 "CAPI Hangingup\n");
++
++    if (i == NULL) {
++      ast_log(LOG_ERROR,"channel has no interface!\n");
++      return -1;
++    }
++    
++    // are we down, yet?
++    if (i->state != CAPI_STATE_DISCONNECTED) {
++      // no
++      capi_activehangup(c);
++    }
++
++    remove_pipe(i->PLCI);
++    i->PLCI = 0;
++    i->NCCI = 0;
++    if ((i->doDTMF == 1) && (i->vad != NULL)) {
++      ast_dsp_free(i->vad);
++    }
++    ast_smoother_free(i->smoother); // discard any frames left hanging
++    i->smoother=ast_smoother_new(AST_CAPI_MAX_B3_BLOCK_SIZE * 2);
++    memset(i->cid,0,sizeof(i->cid));
++    i->owner=NULL;
++    ast_mutex_lock(&usecnt_lock);
++      usecnt--;
++    ast_mutex_unlock(&usecnt_lock);
++    ast_update_use_count();
++    i->mypipe = NULL;
++    i = NULL;
++    c->tech_pvt = NULL;
++    ast_setstate(c,AST_STATE_DOWN);
++    return 0;
++}
++
++static char *capi_number(char *data,int strip) {
++    unsigned len = *data;
++    // XXX fix me
++    // convert a capi struct to a \0 terminated string
++    if (!len || len < (unsigned int) strip) return NULL;
++    len = len - strip;
++    data = (char *)(data + 1 + strip);
++    return strndup((char *)data,len);
++}
++
++int capi_call(struct ast_channel *c, char *idest, int timeout)
++{
++      struct ast_capi_pvt *i;
++      struct capi_pipe *p = NULL;
++      int fds[2];
++      char *dest,*interface;
++      char buffer[AST_MAX_EXTENSION];
++      char called[AST_MAX_EXTENSION],calling[AST_MAX_EXTENSION];
++      char bchaninfo[3];
++      long flags;
++              
++      _cmsg CMSG;
++      MESSAGE_EXCHANGE_ERROR  error;
++      
++      strncpy(buffer,idest,sizeof(buffer)-1);
++      interface = strtok(buffer, "/");
++      dest = strtok(NULL, "/");
++
++
++      if (!dest) {
++              ast_log(LOG_WARNING, "Destination %s requires a real destination\n", idest);
++              return -1;
++      }
++      i = c->tech_pvt;
++      i->doB3 = AST_CAPI_B3_DONT; // <homer>DOH</homer>
++
++      // always B3
++      if (((char *)dest)[0] == 'b') {
++          i->doB3 = AST_CAPI_B3_ALWAYS;
++      }
++      // only do B3 on successfull calls
++      if (((char *)dest)[0] == 'B') {
++          i->doB3 = AST_CAPI_B3_ON_SUCCESS;
++      } 
++      
++      if (i->doB3 != AST_CAPI_B3_DONT) {
++          dest++;
++      }
++
++      if (option_verbose > 1) {
++          if (capidebug)
++              ast_verbose(VERBOSE_PREFIX_2 "CAPI Call %s %s", c->name, i->doB3?"with B3":"");
++      }
++      switch (c->cid.cid_pres) {
++          case PRES_ALLOWED_USER_NUMBER_NOT_SCREENED:
++          case PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN:
++          case PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN:
++          case PRES_ALLOWED_NETWORK_NUMBER:
++          case PRES_NUMBER_NOT_AVAILABLE:
++              i->CLIR = 0;
++              break;
++          case PRES_PROHIB_USER_NUMBER_NOT_SCREENED:
++          case PRES_PROHIB_USER_NUMBER_PASSED_SCREEN:
++          case PRES_PROHIB_USER_NUMBER_FAILED_SCREEN:
++          case PRES_PROHIB_NETWORK_NUMBER:
++              i->CLIR = 1;
++              break;
++          default:
++              i->CLIR = 0;
++      }
++    
++      if (pipe(fds) == 0) {
++          ast_mutex_lock(&pipelock);
++          i->fd = fds[0];
++          flags = fcntl(i->fd,F_GETFL);
++          fcntl(i->fd,F_SETFL,flags | O_SYNC | O_DIRECT);
++          p = malloc(sizeof(struct capi_pipe));
++          memset(p, 0, sizeof(struct capi_pipe));
++          p->fd = fds[1];
++          flags = fcntl(i->fd,F_GETFL);
++          fcntl(p->fd,F_SETFL,flags | O_SYNC | O_DIRECT);
++          c->fds[0] = i->fd;
++          p->PLCI = -1;
++          p->i = i;
++          p->c = c;
++          i->mypipe = p;
++          p->next = pipelist;
++          pipelist = p;
++          if (option_verbose > 4) {
++              ast_verbose(VERBOSE_PREFIX_3 "creating pipe for PLCI=-1\n");
++          }
++          ast_mutex_unlock(&pipelock);
++      }
++      i->outgoing = 1;
++      
++      i->MessageNumber = ast_capi_MessageNumber++;
++      CONNECT_REQ_HEADER(&CMSG, ast_capi_ApplID, i->MessageNumber, i->controller);
++      CONNECT_REQ_CONTROLLER(&CMSG) = i->controller;
++      CONNECT_REQ_CIPVALUE(&CMSG) = 0x10;     // Telephony, could also use 0x04 (3.1Khz audio)
++      called[0] = strlen(dest)+1;
++      called[1] = 0x80;
++      strncpy(&called[2],dest,sizeof(called)-2);
++      CONNECT_REQ_CALLEDPARTYNUMBER(&CMSG) = (unsigned char *)called;
++      CONNECT_REQ_CALLEDPARTYSUBADDRESS(&CMSG) = NULL;
++
++      if (c->cid.cid_num) {
++          calling[0] = strlen(c->cid.cid_num)+2;
++          calling[1] = 0x0;
++      } else {
++          calling[0] = 0x0;
++          calling[1] = 0x0;
++      }
++
++      if (i->CLIR == 1) {
++          calling[2] = 0xA0; // CLIR
++      } else {
++          calling[2] = 0x80; // CLIP
++      }
++
++      if (c->cid.cid_num) {
++          strncpy(&calling[3],c->cid.cid_num,sizeof(calling)-3);
++      }
++      CONNECT_REQ_CALLINGPARTYNUMBER(&CMSG) = (unsigned char *)calling;
++      CONNECT_REQ_CALLINGPARTYSUBADDRESS(&CMSG) = NULL;
++
++      CONNECT_REQ_B1PROTOCOL(&CMSG) = 1;
++      CONNECT_REQ_B2PROTOCOL(&CMSG) = 1; // 1
++      CONNECT_REQ_B3PROTOCOL(&CMSG) = 0;
++
++      bchaninfo[0] = 2;
++      bchaninfo[1] = 0x0;
++      bchaninfo[2] = 0x0;
++      CONNECT_REQ_BCHANNELINFORMATION(&CMSG) = (unsigned char *)bchaninfo; // 0
++
++        if ((error = _capi_put_cmsg(&CMSG))) {
++          ast_log(LOG_ERROR,"error sending CONNECT_REQ (error=%#x)\n",error);
++          return error;
++      } else {
++          if (option_verbose > 5) {
++              ast_verbose(VERBOSE_PREFIX_4 "sent CONNECT_REQ MN =%#x\n",CMSG.Messagenumber);
++          }
++      }
++
++      i->state = CAPI_STATE_CONNECTPENDING;
++
++      ast_setstate(c, AST_STATE_DIALING);
++
++      // XXX fixme, not nice:
++/*    if (i->controller > 0) {
++          capi_controllers[i->controller]->nfreebchannels--;
++      } */
++
++      // now we shall return .... the rest has to be done by handle_msg
++    return 0;
++}
++
++
++static int capi_answer(struct ast_channel *c) {
++    struct ast_capi_pvt *i = c->tech_pvt;
++    MESSAGE_EXCHANGE_ERROR  error;
++    _cmsg                 CMSG;
++    char buf[AST_MAX_EXTENSION];
++    char *dnid;
++    
++    if (i->isdnmode && (strlen(i->incomingmsn)<strlen(i->dnid)))
++      dnid = i->dnid + strlen(i->incomingmsn);
++    else
++      dnid = i->dnid;
++
++    CONNECT_RESP_HEADER(&CMSG, ast_capi_ApplID, i->MessageNumber, 0);
++    CONNECT_RESP_PLCI(&CMSG) = i->PLCI;
++    CONNECT_RESP_REJECT(&CMSG) = 0;
++    buf[0] = strlen(dnid)+2;
++    buf[1] = 0x0;
++    buf[2] = 0x80;
++    strncpy(&buf[3],dnid,sizeof(buf)-4);
++    CONNECT_RESP_CONNECTEDNUMBER(&CMSG) = (unsigned char *)buf;
++    CONNECT_RESP_CONNECTEDSUBADDRESS(&CMSG) = NULL;
++    CONNECT_RESP_LLC(&CMSG) = NULL;
++    CONNECT_RESP_B1PROTOCOL(&CMSG) = 1;
++    CONNECT_RESP_B2PROTOCOL(&CMSG) = 1;
++    CONNECT_RESP_B3PROTOCOL(&CMSG) = 0;
++
++    if (option_verbose > 3)
++      ast_verbose(VERBOSE_PREFIX_3 "CAPI Answering for MSN %s\n", dnid);
++    if ((error = _capi_put_cmsg(&CMSG)) != 0) {
++      return -1;      
++    } else {
++      if (option_verbose > 5) {
++          if (capidebug) 
++              ast_verbose(VERBOSE_PREFIX_4 "sent CONNECT_RESP PLCI = %#x DNID = %s\n",i->PLCI,i->dnid);
++      }
++    }
++    
++    i->state = CAPI_STATE_ANSWERING;
++    i->doB3 = AST_CAPI_B3_DONT;
++    i->outgoing = 0;
++    i->earlyB3 = -1;
++
++    return 0;
++}
++
++struct ast_frame *capi_read(struct ast_channel *c) {
++    struct ast_capi_pvt *i = c->tech_pvt;
++      int readsize = 0;
++
++      if ((i->state == CAPI_STATE_REMOTE_HANGUP)) {
++          ast_log(LOG_ERROR,"this channel is not connected\n");
++          return NULL;
++      }
++      if (i->state == CAPI_STATE_ONHOLD) {
++          i->fr.frametype = AST_FRAME_NULL;
++          return &i->fr;
++      }
++      
++      if (i == NULL) {
++          ast_log(LOG_ERROR,"channel has no interface\n");
++          return NULL;
++      }
++      i->fr.frametype = AST_FRAME_NULL;
++      i->fr.subclass = 0;
++      i->fr.delivery.tv_sec = 0;
++      i->fr.delivery.tv_usec = 0;
++      readsize = read(i->fd,&i->fr,sizeof(struct ast_frame));
++      if (readsize != sizeof(struct ast_frame)) {
++          ast_log(LOG_ERROR,"did not read a whole frame\n");
++      }
++      if (i->fr.frametype == AST_FRAME_VOICE) {
++          readsize = read(i->fd,i->fr.data,i->fr.datalen);
++          if (readsize != i->fr.datalen) {
++              ast_log(LOG_ERROR,"did not read whole frame data\n");
++          }
++      }
++      i->fr.mallocd = 0;      
++      if (i->fr.frametype == AST_FRAME_NULL) {
++          return NULL;
++      }
++      if ((i->fr.frametype == AST_FRAME_DTMF) && (i->fr.subclass == 'f')) {
++          if (strcmp(c->exten, "fax")) {
++              if (ast_exists_extension(c, ast_strlen_zero(c->macrocontext) ? c->context : c->macrocontext, "fax", 1, c->cid.cid_num)) {
++                  if (option_verbose > 2)
++                      ast_verbose(VERBOSE_PREFIX_3 "Redirecting %s to fax extension\n", c->name);
++                      /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
++                      pbx_builtin_setvar_helper(c,"FAXEXTEN",c->exten);
++                      if (ast_async_goto(c, c->context, "fax", 1))
++                          ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", c->name, c->context);
++                      } else {
++                          ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
++                      }
++          } else {
++              ast_log(LOG_DEBUG, "Already in a fax extension, not redirecting\n");
++          }
++      }
++      return &i->fr;
++}
++
++int capi_write(struct ast_channel *c, struct ast_frame *f) {
++    struct ast_capi_pvt *i = c->tech_pvt;
++      _cmsg CMSG;
++      MESSAGE_EXCHANGE_ERROR  error;
++      int j=0;
++      char buf[1000];
++      struct ast_frame *fsmooth;
++#ifdef CAPI_ES
++      int txavg=0;
++#endif
++
++#ifndef CAPI_NEVER_EVER_EARLY_B3_CONNECTS
++      // dont send audio to the local exchange!
++      if (i->earlyB3 == 1 || !i->NCCI) {
++          return 0;
++      }
++#endif
++
++      if (!i) {
++          ast_log(LOG_ERROR,"channel has no interface\n");
++          return -1;
++      } 
++
++      if (f->frametype == AST_FRAME_NULL) {
++          return 0;
++      }
++      if (f->frametype == AST_FRAME_DTMF) {
++          ast_log(LOG_ERROR,"dtmf frame should be written\n");
++          return 0;
++      }
++      if (f->frametype != AST_FRAME_VOICE) {
++          ast_log(LOG_ERROR,"not a voice frame\n");
++          return -1;
++      }
++      if (f->subclass != capi_capability) {
++          ast_log(LOG_ERROR,"dont know how to write subclass %d\n",f->subclass);
++          return -1;
++      }
++//    ast_log(LOG_NOTICE,"writing frame %d %d\n",f->frametype,f->subclass);
++
++    if (ast_smoother_feed(i->smoother, f)!=0) {
++        ast_log(LOG_ERROR,"failed to fill smoother\n");
++        return -1;
++    }
++
++    fsmooth=ast_smoother_read(i->smoother);
++    while(fsmooth != NULL) {
++        DATA_B3_REQ_HEADER(&CMSG, ast_capi_ApplID, ast_capi_MessageNumber++, 0);
++        DATA_B3_REQ_NCCI(&CMSG) = i->NCCI;
++        DATA_B3_REQ_DATALENGTH(&CMSG) = fsmooth->datalen;
++        DATA_B3_REQ_FLAGS(&CMSG) = 0; 
++
++        if (ast_mutex_lock(&capi_send_buffer_lock)) {
++            ast_log(LOG_WARNING,"Unable to lock B3 send buffer!\n");
++            return -1;
++        }
++#ifndef CAPI_ES
++#ifdef CAPI_GAIN
++        for (j=0;j<fsmooth->datalen;j++) {
++          buf[j] = i->g.txgains[reversebits[((unsigned char *)fsmooth->data)[j]]]; 
++        }
++#else
++        for (j=0;j<fsmooth->datalen;j++) {
++          buf[j] = reversebits[ ((unsigned char *)fsmooth->data)[j] ]; 
++        }
++#endif
++#else
++      if ((i->doES == 1)) {
++          for (j=0;j<fsmooth->datalen;j++) {
++              buf[j] = reversebits[ ((unsigned char *)fsmooth->data)[j] ]; 
++              txavg += abs( capiXLAW2INT(reversebits[ ((unsigned char*)fsmooth->data)[j]]) );
++          }
++          txavg = txavg/j;
++          for(j=0;j<ECHO_TX_COUNT-1;j++) {
++              i->txavg[j] = i->txavg[j+1];
++          }
++          i->txavg[ECHO_TX_COUNT-1] = txavg;
++          
++//        ast_log(LOG_NOTICE,"txavg = %d\n",txavg);
++      } else {
++#ifdef CAPI_GAIN
++          for (j=0;j<fsmooth->datalen;j++) {
++              buf[j] = i->g.txgains[reversebits[((unsigned char *)fsmooth->data)[j]]]; 
++          }
++#else
++          for (j=0;j<fsmooth->datalen;j++) {
++              buf[j] = reversebits[ ((unsigned char *)fsmooth->data)[j] ]; 
++          }
++#endif
++      }
++#endif
++    
++        DATA_B3_REQ_DATAHANDLE(&CMSG) = capi_send_buffer_handle;
++      memcpy((char *)&capi_send_buffer[(capi_send_buffer_handle % AST_CAPI_MAX_B3_BLOCKS) * AST_CAPI_MAX_B3_BLOCK_SIZE],&buf,fsmooth->datalen);
++        DATA_B3_REQ_DATA(&CMSG) = (unsigned char *)&capi_send_buffer[(capi_send_buffer_handle % AST_CAPI_MAX_B3_BLOCKS) * AST_CAPI_MAX_B3_BLOCK_SIZE];
++      capi_send_buffer_handle++;
++    
++        if (ast_mutex_unlock(&capi_send_buffer_lock)) {
++            ast_log(LOG_WARNING,"Unable to unlock B3 send buffer!\n");
++            return -1;
++        }
++
++
++#ifdef CAPI_SYNC    
++    ast_mutex_lock(&i->lockB3in);
++    if ((i->B3in >= 1) && (i->B3in <= AST_CAPI_MAX_B3_BLOCKS)) {
++      i->B3in--;
++      ast_mutex_unlock(&i->lockB3in);
++        if ((error = _capi_put_cmsg(&CMSG)) != 0) {
++            ast_log(LOG_ERROR,"error sending DATA_B3_REQ (error=%#x, datalen=%d) B3in=%d\n",error,fsmooth->datalen,i->B3in);
++//            ast_log(LOG_NOTICE,"f: timelen %d b = %d MN = %d \n",fsmooth->timelen,b,CMSG.Messagenumber);
++      } else {
++                  if (option_verbose > 5) {
++              if (capidebug) 
++                  ast_verbose(VERBOSE_PREFIX_4 "sent DATA_B3_REQ (NCCI=%#x) (%d bytes)\n",i->NCCI,fsmooth->datalen);
++                  }
++      }
++    } else {
++      if (i->B3in > 0) i->B3in--;
++      ast_mutex_unlock(&i->lockB3in);
++    }
++#else
++        if ((error = _capi_put_cmsg(&CMSG)) != 0) {
++            ast_log(LOG_ERROR,"error sending DATA_B3_REQ (error=%#x, datalen=%d)\n",error,fsmooth->datalen);
++//            ast_log(LOG_NOTICE,"f: timelen %d b = %d MN = %d \n",fsmooth->timelen,b,CMSG.Messagenumber);
++      } else {
++                  if (option_verbose > 5) {
++              if (capidebug) 
++                  ast_verbose(VERBOSE_PREFIX_4 "sent DATA_B3_REQ (NCCI=%#x) (%d bytes)\n",i->NCCI,fsmooth->datalen);
++                  }
++      }
++#endif
++    
++//    ast_frfree(fsmooth);
++
++        fsmooth=ast_smoother_read(i->smoother);
++    }
++      return 0;
++}
++
++static int capi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan) {
++    struct ast_capi_pvt *p = newchan->tech_pvt;
++      p->owner = newchan;
++      return 0;
++}
++
++int capi_indicate(struct ast_channel *c,int condition) {
++    return -1;
++}
++
++int capi_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc) {
++    return -1;
++}
++
++
++struct ast_channel *capi_new(struct ast_capi_pvt *i,int state) {
++    struct ast_channel *tmp;
++    int fmt;
++
++    tmp = ast_channel_alloc(1);
++    if (tmp != NULL) {
++      snprintf(tmp->name,sizeof(tmp->name),"CAPI/contr%d/%s-%d",i->controller,i->dnid,capi_counter++);
++      tmp->type = type;
++      tmp->tech = &capi_tech;
++      tmp->nativeformats = capi_capability;
++      ast_setstate(tmp,state);
++      tmp->fds[0] = i->fd;
++      i->smoother = ast_smoother_new(AST_CAPI_MAX_B3_BLOCK_SIZE);
++      if (i->smoother == NULL) {
++          ast_log(LOG_ERROR, "smoother NULL!\n");
++      }
++      i->fr.frametype = 0;
++      i->fr.subclass = 0;
++      i->fr.delivery.tv_sec = 0;
++      i->fr.delivery.tv_usec = 0;
++      i->state = CAPI_STATE_DISCONNECTED;
++      i->CLIR = 0;
++      i->calledPartyIsISDN = 0; // let's be pessimistic
++      i->earlyB3 = -1;
++      i->doB3 = AST_CAPI_B3_DONT;
++      i->outgoing = 0;
++      i->onholdPLCI = 0;
++#ifdef CAPI_SYNC
++      i->B3in = 0;
++      ast_mutex_init(&i->lockB3in);
++#endif                
++#ifdef CAPI_ES
++      memset(i->txavg,0,ECHO_TX_COUNT);
++#endif
++
++#ifndef CAPI_FORCE_SOFTWARE_DTMF
++          if (i->doDTMF == 1) {
++#endif
++              i->vad = ast_dsp_new();
++              ast_dsp_set_features(i->vad, DSP_FEATURE_DTMF_DETECT);
++#ifndef CAPI_FORCE_SOFTWARE_DTMF
++          }
++#endif
++
++      tmp->tech_pvt = i;
++      tmp->callgroup = i->callgroup;
++      tmp->nativeformats = capi_capability;
++      fmt = ast_best_codec(tmp->nativeformats);
++//    fmt = capi_capability;
++      tmp->readformat = fmt;
++      tmp->writeformat = fmt;
++      tmp->rawreadformat = fmt;
++      tmp->rawwriteformat = fmt;
++      strncpy(tmp->context,i->context,sizeof(tmp->context)-1);
++      tmp->cid.cid_num = strdup(i->cid);
++      tmp->cid.cid_dnid = strdup(i->dnid);
++      strncpy(tmp->exten,i->dnid,sizeof(tmp->exten)-1);
++      strncpy(tmp->accountcode,i->accountcode,sizeof(tmp->accountcode)-1);
++      i->owner = tmp;
++      ast_mutex_lock(&usecnt_lock);
++      usecnt++;
++      ast_mutex_unlock(&usecnt_lock);
++      ast_update_use_count();
++      if (state != AST_STATE_DOWN) {
++          // we are alerting (phones ringing)
++          if (state == AST_STATE_RING)
++              capi_alert(tmp);
++          if (ast_pbx_start(tmp)) {
++              ast_log(LOG_ERROR,"Unable to start pbx on channel!\n");
++              ast_hangup(tmp);
++              tmp = NULL;
++          } else {
++              if (option_verbose > 2) {
++                  ast_verbose(VERBOSE_PREFIX_3 "started pbx on channel (callgroup=%d)!\n",tmp->callgroup);
++              }
++          }
++      }
++    } else {
++      ast_log(LOG_ERROR,"Unable to allocate channel!\n");
++    }
++    return tmp;
++}
++
++
++struct ast_channel *capi_request(const char *type, int format, void *data, int *cause)
++{
++      struct ast_capi_pvt *i;
++      struct ast_channel *tmp = NULL;
++      char *dest,*interface;
++      char buffer[AST_MAX_EXTENSION];
++      unsigned int capigroup=0, controller=0;
++      int notfound = 1;
++
++      if (option_verbose > 1) {
++          if (capidebug)
++              ast_verbose(VERBOSE_PREFIX_3 "data = %s\n",(char *)data);
++      }
++      strncpy(buffer,(char *)data,sizeof(buffer)-1);
++
++      interface = strtok(buffer, "/");
++      dest = strtok(NULL, "/");
++
++      
++      if (((char *)interface)[0] == 'g') {
++          interface++;
++          capigroup = atoi(interface);
++          if (option_verbose > 1) {
++              if (capidebug)
++                  ast_verbose(VERBOSE_PREFIX_3 "capi request group = %d\n",capigroup);
++          }
++      } else if (!strncmp(interface,"contr",5)) {
++          interface += 5;
++          controller = atoi(interface);
++          if (option_verbose > 1) {
++              if (capidebug)
++                  ast_verbose(VERBOSE_PREFIX_3 "capi request controller = %d\n",controller);
++          }
++      } else {
++          ast_log(LOG_ERROR,"Syntax error in dialstring. read the docs!\n");
++      }
++
++      ast_mutex_lock(&iflock);
++      i = iflist;
++      while (i && notfound) {
++          // unused channel
++          if (!i->owner) {
++              if (controller && (i->controllers & (1 << controller))) {
++                  // DIAL(CAPI/contrX/...)
++                  ast_mutex_lock(&contrlock);
++                  if (capi_controllers[controller]->nfreebchannels > 0) {
++                      strncpy(i->dnid,dest,sizeof(i->dnid)-1);
++                      i->controller = controller;
++                      tmp = capi_new(i, AST_STATE_DOWN);
++                      i->PLCI = -1;
++                      i->datahandle = 0;
++                      i->outgoing = 1;        // this is an outgoing line
++                      i->earlyB3 = -1;
++                      // capi_detect_dtmf(tmp,1);
++                      ast_mutex_unlock(&contrlock);
++                      ast_mutex_unlock(&iflock);
++                      return tmp;
++                  } else {
++                      // keep on running!
++                      ast_mutex_unlock(&contrlock);
++                  }
++              } else if (capigroup && (i->group & (1 << capigroup))) {
++                  int c;
++                  // DIAL(CAPI/gX/...)
++                  ast_mutex_lock(&contrlock);
++                  for (c=1;c<=capi_num_controllers;c++) {
++                      if (i->controllers & (1 << c)) {
++                          if (capi_controllers[c]->nfreebchannels > 0) {
++                              strncpy(i->dnid,dest,sizeof(i->dnid)-1);
++                              i->controller = c;
++                              tmp = capi_new(i, AST_STATE_DOWN);
++                              i->PLCI = -1;
++                              i->datahandle = 0;
++                              i->outgoing = 1;        // this is an outgoing line
++                              i->earlyB3 = -1;
++                              // capi_detect_dtmf(tmp,1);
++                              ast_mutex_unlock(&contrlock);
++                              ast_mutex_unlock(&iflock);
++                              return tmp;
++                          } else {
++                              // keep on running!
++                          }
++                      }
++                  }
++                  ast_mutex_unlock(&contrlock);
++              }
++          }
++//        ast_log(LOG_NOTICE,"not contr %d group %d\n",i->controllers, i->group);
++          i = i->next;
++      }
++      ast_mutex_unlock(&iflock);
++      ast_log(LOG_NOTICE,"didn't find capi device with controller = %d or group = %d.\n",controller, capigroup);
++      return NULL;
++}
++
++
++struct capi_pipe *find_pipe(int PLCI,int MN) {
++    struct capi_pipe *p;
++    // find a pipe by PLCI or by MessageNumber (in case this is a CONNECT_CONF)
++    ast_mutex_lock(&pipelock);
++    p = pipelist;
++    if ((p == NULL) && (capi_last_plci != PLCI)){
++      if (capidebug) {
++      ast_log(LOG_NOTICE,"PLCI doesnt match last pipe (PLCI = %#x)\n",PLCI);
++      }
++      ast_mutex_unlock(&pipelock);
++      return NULL;
++    }
++    while(p != NULL) {
++      if ((p->PLCI == PLCI) || ( (p->PLCI == -1) && (p->i->MessageNumber == MN) ) ){
++          ast_mutex_unlock(&pipelock);
++          return p;
++      }
++      p = p->next;
++    }
++    if (capidebug) {
++      ast_log(LOG_ERROR,"unable to find a pipe for PLCI = %#x MN = %#x\n",PLCI,MN);
++    }
++    ast_mutex_unlock(&pipelock);
++    return NULL;
++}
++
++int pipe_frame(struct capi_pipe *p,struct ast_frame *f) {
++      fd_set wfds;
++      int written=0;
++      struct timeval tv;
++      FD_ZERO(&wfds);
++      FD_SET(p->fd,&wfds);
++      tv.tv_sec = 0;
++      tv.tv_usec = 10;
++      if ((f->frametype == AST_FRAME_VOICE) && (p->i->doDTMF == 1) && (p->i->vad != NULL)) {
++          f = ast_dsp_process(p->c,p->i->vad,f);
++          if (f->frametype == AST_FRAME_NULL) {
++              return 0;
++          }
++      }
++      // we dont want the monitor thread to block
++      if (select(p->fd + 1,NULL,&wfds,NULL,&tv) == 1) {
++          written = write(p->fd,f,sizeof(struct ast_frame));
++          if (written < (signed int) sizeof(struct ast_frame)) {
++              ast_log(LOG_ERROR,"wrote %d bytes instead of %d\n", written, (int)sizeof(struct ast_frame));
++              return -1;
++          }
++          if (f->frametype == AST_FRAME_VOICE) {
++              written = write(p->fd,f->data,f->datalen);
++              if (written < f->datalen) {
++                  ast_log(LOG_ERROR,"wrote %d bytes instead of %d\n",written,f->datalen);
++                  return -1;
++              }
++          }
++      } else {
++          return 0;
++      }
++      return -1;
++}
++
++static int search_did(struct ast_channel *c)
++{
++    // Returns 
++    // -1 = Failure 
++    //  0 = Match
++    //  1 = possible match 
++    struct ast_capi_pvt *i = c->tech_pvt;
++    char *exten;
++    
++    if (strlen(i->dnid)<strlen(i->incomingmsn))
++      return -1;
++      
++//    exten = i->dnid + strlen(i->incomingmsn);
++    exten = i->dnid;
++
++    if (ast_exists_extension(NULL, c->context, exten, 1, NULL)) {
++          c->priority = 1;
++          strncpy(c->exten, exten, sizeof(c->exten) - 1);
++      return 0;
++    }
++
++    if (ast_canmatch_extension(NULL, c->context, exten, 1, NULL)) {
++      return 1;
++    }
++
++
++    return -1;
++}
++
++int pipe_msg(int PLCI,_cmsg *CMSG) {
++      struct capi_pipe *p;
++      _cmsg CMSG2;
++      MESSAGE_EXCHANGE_ERROR  error;
++      struct ast_frame fr;
++      char b3buf[1024];
++      int j;
++      int b3len=0;
++      char dtmf;
++      unsigned dtmflen;
++#ifdef CAPI_ES
++      int rxavg = 0;
++      int txavg = 0;
++#endif    
++
++      p = find_pipe(PLCI,CMSG->Messagenumber);
++      if (p == NULL) {
++          if (IS_DISCONNECT_IND(CMSG)) {
++              DISCONNECT_RESP_HEADER(&CMSG2, ast_capi_ApplID, CMSG->Messagenumber , 0);
++              DISCONNECT_RESP_PLCI(&CMSG2) = PLCI;
++              if ((error = _capi_put_cmsg(&CMSG2)) != 0) {
++                  ast_log(LOG_NOTICE, "error sending DISCONNECT_RESP PLCI=%#x\n",PLCI);
++              } else {
++                  if (option_verbose > 5) {
++                      if (capidebug)
++                          ast_verbose(VERBOSE_PREFIX_4 "sent DISCONNECT_RESP PLCI=%#x\n",PLCI);
++                  }